From 581b8c71b836746c5647af6854c36be9a3af4c1e Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Mon, 1 May 2023 07:49:17 +1200 Subject: [PATCH 01/15] Prepare repo --- .eslintrc.js | 23 + .gitignore | 11 + .gitmodules | 3 + .prettierrc.js | 6 + .vscode/settings.json | 8 + LICENSE | 219 ++++++++ cache/solidity-files-cache.json | 930 ++++++++++++++++++++++++++++++++ foundry.toml | 5 + lib/forge-std | 1 + package.json | 27 + remappings.txt | 4 + script/Counter.s.sol | 12 + src/Counter.sol | 14 + test/Counter.t.sol | 23 + yarn.lock | 487 +++++++++++++++++ 15 files changed, 1773 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .prettierrc.js create mode 100644 .vscode/settings.json create mode 100644 LICENSE create mode 100644 cache/solidity-files-cache.json create mode 100644 foundry.toml create mode 160000 lib/forge-std create mode 100644 package.json create mode 100644 remappings.txt create mode 100644 script/Counter.s.sol create mode 100644 src/Counter.sol create mode 100644 test/Counter.t.sol create mode 100644 yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..6ce781d5 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,23 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + }, + + extends: [ + 'eslint:recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + plugins: ['@typescript-eslint', 'simple-import-sort'], + + rules: { + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/consistent-type-imports': 'error', + }, + + ignorePatterns: ['dist', 'node_modules'], +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f6d6fa41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules/ +out/ + +# Ignore .DS_Store files on macOS +.DS_Store + +# Yarn +yarn-error.log + +# Env vars +.env diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..888d42dc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..9050f2a4 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + arrowParens: 'avoid', + semi: false, + singleQuote: true, + trailingComma: 'all', +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..9f270f1c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "[solidity]": { + "editor.defaultFormatter": "JuanBlanco.solidity" + }, + "solidity.formatter": "forge", + "solidity.compileUsingRemoteVersion": "v0.8.17" +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..df07b303 --- /dev/null +++ b/LICENSE @@ -0,0 +1,219 @@ + Copyright (c) 2023-present Horizon Blockchain Games Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + ------------------------------------------------------------------------ + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json new file mode 100644 index 00000000..aea65078 --- /dev/null +++ b/cache/solidity-files-cache.json @@ -0,0 +1,930 @@ +{ + "_format": "ethers-rs-sol-cache-3", + "paths": { + "artifacts": "out", + "build_infos": "out/build-info", + "sources": "src", + "tests": "test", + "scripts": "script", + "libraries": [ + "lib" + ] + }, + "files": { + "lib/forge-std/lib/ds-test/src/test.sol": { + "lastModificationDate": 1682560435533, + "contentHash": "2df678a5b2611e0d7bc9ef6745d19157", + "sourceName": "lib/forge-std/lib/ds-test/src/test.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.5.0", + "artifacts": { + "DSTest": { + "0.8.17+commit.8df45f5f.Windows.msvc": "test.sol\\DSTest.json" + } + } + }, + "lib/forge-std/src/Base.sol": { + "lastModificationDate": 1682560430784, + "contentHash": "2a76a316dab98751b739247982ac8576", + "sourceName": "lib/forge-std/src/Base.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "CommonBase": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\CommonBase.json" + }, + "ScriptBase": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\ScriptBase.json" + }, + "TestBase": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\TestBase.json" + } + } + }, + "lib/forge-std/src/Script.sol": { + "lastModificationDate": 1682560430785, + "contentHash": "c10ed2980061827d4a5ce78c310ae01b", + "sourceName": "lib/forge-std/src/Script.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Base.sol", + "lib/forge-std/src/StdChains.sol", + "lib/forge-std/src/StdCheats.sol", + "lib/forge-std/src/StdJson.sol", + "lib/forge-std/src/StdMath.sol", + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/StdUtils.sol", + "lib/forge-std/src/Vm.sol", + "lib/forge-std/src/console.sol", + "lib/forge-std/src/console2.sol", + "lib/forge-std/src/interfaces/IMulticall3.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "Script": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Script.sol\\Script.json" + } + } + }, + "lib/forge-std/src/StdAssertions.sol": { + "lastModificationDate": 1682560430787, + "contentHash": "d136ed3be15b16e8875196a38f225c2f", + "sourceName": "lib/forge-std/src/StdAssertions.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/lib/ds-test/src\\test.sol", + "lib/forge-std/src/StdMath.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "StdAssertions": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdAssertions.sol\\StdAssertions.json" + } + } + }, + "lib/forge-std/src/StdChains.sol": { + "lastModificationDate": 1682560430787, + "contentHash": "782a4e3904d3ec80179253920e1f3098", + "sourceName": "lib/forge-std/src/StdChains.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "StdChains": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdChains.sol\\StdChains.json" + } + } + }, + "lib/forge-std/src/StdCheats.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "27f7037d3ce568cac654c20032ed71e3", + "sourceName": "lib/forge-std/src/StdCheats.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "StdCheats": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdCheats.sol\\StdCheats.json" + }, + "StdCheatsSafe": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdCheats.sol\\StdCheatsSafe.json" + } + } + }, + "lib/forge-std/src/StdError.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "8c35ad419c5b8748575080db5fd58cae", + "sourceName": "lib/forge-std/src/StdError.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "stdError": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdError.sol\\stdError.json" + } + } + }, + "lib/forge-std/src/StdInvariant.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "3525c75dbb49f9af908a943d9ea635cf", + "sourceName": "lib/forge-std/src/StdInvariant.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "StdInvariant": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdInvariant.sol\\StdInvariant.json" + } + } + }, + "lib/forge-std/src/StdJson.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "71c2c9083583f2adbe0d07a725689def", + "sourceName": "lib/forge-std/src/StdJson.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.6.0, <0.9.0", + "artifacts": { + "stdJson": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdJson.sol\\stdJson.json" + } + } + }, + "lib/forge-std/src/StdMath.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "fc64b149e462e64dea89f50e9cc0318f", + "sourceName": "lib/forge-std/src/StdMath.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "stdMath": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdMath.sol\\stdMath.json" + } + } + }, + "lib/forge-std/src/StdStorage.sol": { + "lastModificationDate": 1682560430788, + "contentHash": "956a40f1cecbf085f687f818356dc22a", + "sourceName": "lib/forge-std/src/StdStorage.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "stdStorage": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdStorage.sol\\stdStorage.json" + }, + "stdStorageSafe": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdStorage.sol\\stdStorageSafe.json" + } + } + }, + "lib/forge-std/src/StdStyle.sol": { + "lastModificationDate": 1682560430793, + "contentHash": "bc32c9e9afd157bb02836b279d2223c5", + "sourceName": "lib/forge-std/src/StdStyle.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Vm.sol" + ], + "versionRequirement": ">=0.4.22, <0.9.0", + "artifacts": { + "StdStyle": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdStyle.sol\\StdStyle.json" + } + } + }, + "lib/forge-std/src/StdUtils.sol": { + "lastModificationDate": 1682560430794, + "contentHash": "2b2cfd9859c68fa78b9e2aff05a80d87", + "sourceName": "lib/forge-std/src/StdUtils.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Vm.sol", + "lib/forge-std/src/interfaces/IMulticall3.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "StdUtils": { + "0.8.17+commit.8df45f5f.Windows.msvc": "StdUtils.sol\\StdUtils.json" + } + } + }, + "lib/forge-std/src/Test.sol": { + "lastModificationDate": 1682560430795, + "contentHash": "53342ae9785fc6ae53971b57c6ab41d3", + "sourceName": "lib/forge-std/src/Test.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/lib/ds-test/src\\test.sol", + "lib/forge-std/src/Base.sol", + "lib/forge-std/src/StdAssertions.sol", + "lib/forge-std/src/StdChains.sol", + "lib/forge-std/src/StdCheats.sol", + "lib/forge-std/src/StdError.sol", + "lib/forge-std/src/StdInvariant.sol", + "lib/forge-std/src/StdJson.sol", + "lib/forge-std/src/StdMath.sol", + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/StdStyle.sol", + "lib/forge-std/src/StdUtils.sol", + "lib/forge-std/src/Vm.sol", + "lib/forge-std/src/console.sol", + "lib/forge-std/src/console2.sol", + "lib/forge-std/src/interfaces/IMulticall3.sol" + ], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "Test": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Test.sol\\Test.json" + } + } + }, + "lib/forge-std/src/Vm.sol": { + "lastModificationDate": 1682560430798, + "contentHash": "0e488a43bb880f32d1ce6f1b86f24359", + "sourceName": "lib/forge-std/src/Vm.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "Vm": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Vm.sol\\Vm.json" + }, + "VmSafe": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Vm.sol\\VmSafe.json" + } + } + }, + "lib/forge-std/src/console.sol": { + "lastModificationDate": 1682560430799, + "contentHash": "c8cf989d04bc2e3069e3d91facf3b69c", + "sourceName": "lib/forge-std/src/console.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.4.22, <0.9.0", + "artifacts": { + "console": { + "0.8.17+commit.8df45f5f.Windows.msvc": "console.sol\\console.json" + } + } + }, + "lib/forge-std/src/console2.sol": { + "lastModificationDate": 1682560430799, + "contentHash": "f0634a1969c1d0ebfc2ea47dafeafb02", + "sourceName": "lib/forge-std/src/console2.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.4.22, <0.9.0", + "artifacts": { + "console2": { + "0.8.17+commit.8df45f5f.Windows.msvc": "console2.sol\\console2.json" + } + } + }, + "lib/forge-std/src/interfaces/IMulticall3.sol": { + "lastModificationDate": 1682560430807, + "contentHash": "5de707a0d82c8f56049fbd3ba28944ed", + "sourceName": "lib/forge-std/src/interfaces/IMulticall3.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": ">=0.6.2, <0.9.0", + "artifacts": { + "IMulticall3": { + "0.8.17+commit.8df45f5f.Windows.msvc": "IMulticall3.sol\\IMulticall3.json" + } + } + }, + "script/Counter.s.sol": { + "lastModificationDate": 1682560427326, + "contentHash": "0705c52104730a78aef4aa6694175c81", + "sourceName": "script/Counter.s.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/src/Base.sol", + "lib/forge-std/src\\Script.sol", + "lib/forge-std/src/StdChains.sol", + "lib/forge-std/src/StdCheats.sol", + "lib/forge-std/src/StdJson.sol", + "lib/forge-std/src/StdMath.sol", + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/StdUtils.sol", + "lib/forge-std/src/Vm.sol", + "lib/forge-std/src/console.sol", + "lib/forge-std/src/console2.sol", + "lib/forge-std/src/interfaces/IMulticall3.sol" + ], + "versionRequirement": "^0.8.13", + "artifacts": { + "CounterScript": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.s.sol\\CounterScript.json" + } + } + }, + "src/Counter.sol": { + "lastModificationDate": 1682560427326, + "contentHash": "ae6c800a2b4c57768024d6e9423d39e8", + "sourceName": "src/Counter.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [], + "versionRequirement": "^0.8.13", + "artifacts": { + "Counter": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.sol\\Counter.json" + } + } + }, + "test/Counter.t.sol": { + "lastModificationDate": 1682560427326, + "contentHash": "5122f4f87ee8fbf9a2468a4c9c780b6a", + "sourceName": "test/Counter.t.sol", + "solcConfig": { + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "": [ + "ast" + ], + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } + }, + "imports": [ + "lib/forge-std/lib/ds-test/src\\test.sol", + "lib/forge-std/src/Base.sol", + "lib/forge-std/src/StdAssertions.sol", + "lib/forge-std/src/StdChains.sol", + "lib/forge-std/src/StdCheats.sol", + "lib/forge-std/src/StdError.sol", + "lib/forge-std/src/StdInvariant.sol", + "lib/forge-std/src/StdJson.sol", + "lib/forge-std/src/StdMath.sol", + "lib/forge-std/src/StdStorage.sol", + "lib/forge-std/src/StdStyle.sol", + "lib/forge-std/src/StdUtils.sol", + "lib/forge-std/src\\Test.sol", + "lib/forge-std/src/Vm.sol", + "lib/forge-std/src/console.sol", + "lib/forge-std/src/console2.sol", + "lib/forge-std/src/interfaces/IMulticall3.sol", + "src\\Counter.sol" + ], + "versionRequirement": "^0.8.13", + "artifacts": { + "CounterTest": { + "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.t.sol\\CounterTest.json" + } + } + } + } +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 00000000..dcfcb1d3 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,5 @@ +[profile.default] +src = 'src' +out = 'out' +libs = ['lib'] +solc = "0.8.17" diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 00000000..73d44ec7 --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 73d44ec7d124e3831bc5f832267889ffb6f9bc3f diff --git a/package.json b/package.json new file mode 100644 index 00000000..62e46fec --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "@0xsequence/contracts-library", + "version": "1.0.0", + "description": "Solidity Contract Library for 0xSequence", + "repository": "https://github.com/0xsequence/contract-library.git", + "bugs": { + "url": "https://github.com/0xsequence/contract-library/issues" + }, + "homepage": "https://github.com/0xsequence/contract-library#README.md", + "source": "src/index.ts", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "author": "Horizon Blockchain Games", + "license": "Apache-2.0", + "scripts": { + "build": "forge build" + }, + "files": [ + "src", + "dist" + ], + "dependencies": { + "@0xsequence/erc-1155": "^4.0.1", + "@0xsequence/erc20-meta-token": "^4.0.1", + "erc721a": "^4.2.3" + } +} diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..17deda06 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,4 @@ +ds-test/=lib/forge-std/lib/ds-test/src/ +forge-std/=lib/forge-std/src/ +@0xsequence/erc20-meta-token/=node_modules/@0xsequence/erc20-meta-token/ +@0xsequence/erc-1155/=node_modules/@0xsequence/erc-1155/ diff --git a/script/Counter.s.sol b/script/Counter.s.sol new file mode 100644 index 00000000..0e546aba --- /dev/null +++ b/script/Counter.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; + +contract CounterScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + } +} diff --git a/src/Counter.sol b/src/Counter.sol new file mode 100644 index 00000000..aded7997 --- /dev/null +++ b/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/test/Counter.t.sol b/test/Counter.t.sol new file mode 100644 index 00000000..fc5accfd --- /dev/null +++ b/test/Counter.t.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function testIncrement() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testSetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..334f784e --- /dev/null +++ b/yarn.lock @@ -0,0 +1,487 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@0xsequence/erc-1155@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@0xsequence/erc-1155/-/erc-1155-4.0.1.tgz#c991fe06b6ae385146e69cd9d1c4982b06487c10" + integrity sha512-KFLxBfiocOuHmPUkGYiWw5fLZ8uCDhXhcyzFFv8oe/KWXdxL37NTD7n6CmMSRiUxr4qaXuFV5u38vPFWFdOY0g== + optionalDependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + ethers "^5.7.2" + +"@0xsequence/erc20-meta-token@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@0xsequence/erc20-meta-token/-/erc20-meta-token-4.0.1.tgz#44fe77822af0ff3b1111466615c9958e92aca782" + integrity sha512-q3yIR5OwsTK+HnTQVXTDlknMo2kE65rBwZN6ymPeoe1CW+RE9XqUM3QCvxTlLGuAnsIaL6/ABG2ePX4crMvbaw== + dependencies: + "@0xsequence/erc-1155" "^4.0.1" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@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== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@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== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@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== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@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== + dependencies: + "@ethersproject/bignumber" "^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== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@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== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@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== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@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== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@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== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@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== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@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== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +erc721a@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/erc721a/-/erc721a-4.2.3.tgz#ca6469b0e54afb0f614272c2147dc4cb49ff223f" + integrity sha512-0deF0hOOK1XI1Vxv3NKDh2E9sgzRlENuOoexjXRJIRfYCsLlqi9ejl2RF6Wcd9HfH0ldqC03wleQ2WDjxoOUvA== + +ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "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/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +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 sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== From 7207fe77f97aa83b4c556f24d194d44398c16723 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Mon, 1 May 2023 08:06:24 +1200 Subject: [PATCH 02/15] Add linting --- .gitignore | 4 +- .husky/pre-commit | 4 + cache/solidity-files-cache.json | 930 -------------------------------- package.json | 11 +- test/Counter.t.sol | 5 +- yarn.lock | 493 +++++++++++++++++ 6 files changed, 513 insertions(+), 934 deletions(-) create mode 100644 .husky/pre-commit delete mode 100644 cache/solidity-files-cache.json diff --git a/.gitignore b/.gitignore index f6d6fa41..646835db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ -node_modules/ +# Forge out/ +cache/ # Ignore .DS_Store files on macOS .DS_Store # Yarn +node_modules/ yarn-error.log # Env vars diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..5a182ef1 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn lint-staged diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json deleted file mode 100644 index aea65078..00000000 --- a/cache/solidity-files-cache.json +++ /dev/null @@ -1,930 +0,0 @@ -{ - "_format": "ethers-rs-sol-cache-3", - "paths": { - "artifacts": "out", - "build_infos": "out/build-info", - "sources": "src", - "tests": "test", - "scripts": "script", - "libraries": [ - "lib" - ] - }, - "files": { - "lib/forge-std/lib/ds-test/src/test.sol": { - "lastModificationDate": 1682560435533, - "contentHash": "2df678a5b2611e0d7bc9ef6745d19157", - "sourceName": "lib/forge-std/lib/ds-test/src/test.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.5.0", - "artifacts": { - "DSTest": { - "0.8.17+commit.8df45f5f.Windows.msvc": "test.sol\\DSTest.json" - } - } - }, - "lib/forge-std/src/Base.sol": { - "lastModificationDate": 1682560430784, - "contentHash": "2a76a316dab98751b739247982ac8576", - "sourceName": "lib/forge-std/src/Base.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "CommonBase": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\CommonBase.json" - }, - "ScriptBase": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\ScriptBase.json" - }, - "TestBase": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Base.sol\\TestBase.json" - } - } - }, - "lib/forge-std/src/Script.sol": { - "lastModificationDate": 1682560430785, - "contentHash": "c10ed2980061827d4a5ce78c310ae01b", - "sourceName": "lib/forge-std/src/Script.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Base.sol", - "lib/forge-std/src/StdChains.sol", - "lib/forge-std/src/StdCheats.sol", - "lib/forge-std/src/StdJson.sol", - "lib/forge-std/src/StdMath.sol", - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/StdUtils.sol", - "lib/forge-std/src/Vm.sol", - "lib/forge-std/src/console.sol", - "lib/forge-std/src/console2.sol", - "lib/forge-std/src/interfaces/IMulticall3.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "Script": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Script.sol\\Script.json" - } - } - }, - "lib/forge-std/src/StdAssertions.sol": { - "lastModificationDate": 1682560430787, - "contentHash": "d136ed3be15b16e8875196a38f225c2f", - "sourceName": "lib/forge-std/src/StdAssertions.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/lib/ds-test/src\\test.sol", - "lib/forge-std/src/StdMath.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "StdAssertions": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdAssertions.sol\\StdAssertions.json" - } - } - }, - "lib/forge-std/src/StdChains.sol": { - "lastModificationDate": 1682560430787, - "contentHash": "782a4e3904d3ec80179253920e1f3098", - "sourceName": "lib/forge-std/src/StdChains.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "StdChains": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdChains.sol\\StdChains.json" - } - } - }, - "lib/forge-std/src/StdCheats.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "27f7037d3ce568cac654c20032ed71e3", - "sourceName": "lib/forge-std/src/StdCheats.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "StdCheats": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdCheats.sol\\StdCheats.json" - }, - "StdCheatsSafe": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdCheats.sol\\StdCheatsSafe.json" - } - } - }, - "lib/forge-std/src/StdError.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "8c35ad419c5b8748575080db5fd58cae", - "sourceName": "lib/forge-std/src/StdError.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "stdError": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdError.sol\\stdError.json" - } - } - }, - "lib/forge-std/src/StdInvariant.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "3525c75dbb49f9af908a943d9ea635cf", - "sourceName": "lib/forge-std/src/StdInvariant.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "StdInvariant": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdInvariant.sol\\StdInvariant.json" - } - } - }, - "lib/forge-std/src/StdJson.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "71c2c9083583f2adbe0d07a725689def", - "sourceName": "lib/forge-std/src/StdJson.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.6.0, <0.9.0", - "artifacts": { - "stdJson": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdJson.sol\\stdJson.json" - } - } - }, - "lib/forge-std/src/StdMath.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "fc64b149e462e64dea89f50e9cc0318f", - "sourceName": "lib/forge-std/src/StdMath.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "stdMath": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdMath.sol\\stdMath.json" - } - } - }, - "lib/forge-std/src/StdStorage.sol": { - "lastModificationDate": 1682560430788, - "contentHash": "956a40f1cecbf085f687f818356dc22a", - "sourceName": "lib/forge-std/src/StdStorage.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "stdStorage": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdStorage.sol\\stdStorage.json" - }, - "stdStorageSafe": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdStorage.sol\\stdStorageSafe.json" - } - } - }, - "lib/forge-std/src/StdStyle.sol": { - "lastModificationDate": 1682560430793, - "contentHash": "bc32c9e9afd157bb02836b279d2223c5", - "sourceName": "lib/forge-std/src/StdStyle.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Vm.sol" - ], - "versionRequirement": ">=0.4.22, <0.9.0", - "artifacts": { - "StdStyle": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdStyle.sol\\StdStyle.json" - } - } - }, - "lib/forge-std/src/StdUtils.sol": { - "lastModificationDate": 1682560430794, - "contentHash": "2b2cfd9859c68fa78b9e2aff05a80d87", - "sourceName": "lib/forge-std/src/StdUtils.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Vm.sol", - "lib/forge-std/src/interfaces/IMulticall3.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "StdUtils": { - "0.8.17+commit.8df45f5f.Windows.msvc": "StdUtils.sol\\StdUtils.json" - } - } - }, - "lib/forge-std/src/Test.sol": { - "lastModificationDate": 1682560430795, - "contentHash": "53342ae9785fc6ae53971b57c6ab41d3", - "sourceName": "lib/forge-std/src/Test.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/lib/ds-test/src\\test.sol", - "lib/forge-std/src/Base.sol", - "lib/forge-std/src/StdAssertions.sol", - "lib/forge-std/src/StdChains.sol", - "lib/forge-std/src/StdCheats.sol", - "lib/forge-std/src/StdError.sol", - "lib/forge-std/src/StdInvariant.sol", - "lib/forge-std/src/StdJson.sol", - "lib/forge-std/src/StdMath.sol", - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/StdStyle.sol", - "lib/forge-std/src/StdUtils.sol", - "lib/forge-std/src/Vm.sol", - "lib/forge-std/src/console.sol", - "lib/forge-std/src/console2.sol", - "lib/forge-std/src/interfaces/IMulticall3.sol" - ], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "Test": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Test.sol\\Test.json" - } - } - }, - "lib/forge-std/src/Vm.sol": { - "lastModificationDate": 1682560430798, - "contentHash": "0e488a43bb880f32d1ce6f1b86f24359", - "sourceName": "lib/forge-std/src/Vm.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "Vm": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Vm.sol\\Vm.json" - }, - "VmSafe": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Vm.sol\\VmSafe.json" - } - } - }, - "lib/forge-std/src/console.sol": { - "lastModificationDate": 1682560430799, - "contentHash": "c8cf989d04bc2e3069e3d91facf3b69c", - "sourceName": "lib/forge-std/src/console.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.4.22, <0.9.0", - "artifacts": { - "console": { - "0.8.17+commit.8df45f5f.Windows.msvc": "console.sol\\console.json" - } - } - }, - "lib/forge-std/src/console2.sol": { - "lastModificationDate": 1682560430799, - "contentHash": "f0634a1969c1d0ebfc2ea47dafeafb02", - "sourceName": "lib/forge-std/src/console2.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.4.22, <0.9.0", - "artifacts": { - "console2": { - "0.8.17+commit.8df45f5f.Windows.msvc": "console2.sol\\console2.json" - } - } - }, - "lib/forge-std/src/interfaces/IMulticall3.sol": { - "lastModificationDate": 1682560430807, - "contentHash": "5de707a0d82c8f56049fbd3ba28944ed", - "sourceName": "lib/forge-std/src/interfaces/IMulticall3.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.6.2, <0.9.0", - "artifacts": { - "IMulticall3": { - "0.8.17+commit.8df45f5f.Windows.msvc": "IMulticall3.sol\\IMulticall3.json" - } - } - }, - "script/Counter.s.sol": { - "lastModificationDate": 1682560427326, - "contentHash": "0705c52104730a78aef4aa6694175c81", - "sourceName": "script/Counter.s.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/src/Base.sol", - "lib/forge-std/src\\Script.sol", - "lib/forge-std/src/StdChains.sol", - "lib/forge-std/src/StdCheats.sol", - "lib/forge-std/src/StdJson.sol", - "lib/forge-std/src/StdMath.sol", - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/StdUtils.sol", - "lib/forge-std/src/Vm.sol", - "lib/forge-std/src/console.sol", - "lib/forge-std/src/console2.sol", - "lib/forge-std/src/interfaces/IMulticall3.sol" - ], - "versionRequirement": "^0.8.13", - "artifacts": { - "CounterScript": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.s.sol\\CounterScript.json" - } - } - }, - "src/Counter.sol": { - "lastModificationDate": 1682560427326, - "contentHash": "ae6c800a2b4c57768024d6e9423d39e8", - "sourceName": "src/Counter.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": "^0.8.13", - "artifacts": { - "Counter": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.sol\\Counter.json" - } - } - }, - "test/Counter.t.sol": { - "lastModificationDate": 1682560427326, - "contentHash": "5122f4f87ee8fbf9a2468a4c9c780b6a", - "sourceName": "test/Counter.t.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [ - "lib/forge-std/lib/ds-test/src\\test.sol", - "lib/forge-std/src/Base.sol", - "lib/forge-std/src/StdAssertions.sol", - "lib/forge-std/src/StdChains.sol", - "lib/forge-std/src/StdCheats.sol", - "lib/forge-std/src/StdError.sol", - "lib/forge-std/src/StdInvariant.sol", - "lib/forge-std/src/StdJson.sol", - "lib/forge-std/src/StdMath.sol", - "lib/forge-std/src/StdStorage.sol", - "lib/forge-std/src/StdStyle.sol", - "lib/forge-std/src/StdUtils.sol", - "lib/forge-std/src\\Test.sol", - "lib/forge-std/src/Vm.sol", - "lib/forge-std/src/console.sol", - "lib/forge-std/src/console2.sol", - "lib/forge-std/src/interfaces/IMulticall3.sol", - "src\\Counter.sol" - ], - "versionRequirement": "^0.8.13", - "artifacts": { - "CounterTest": { - "0.8.17+commit.8df45f5f.Windows.msvc": "Counter.t.sol\\CounterTest.json" - } - } - } - } -} \ No newline at end of file diff --git a/package.json b/package.json index 62e46fec..e7f5bc36 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "author": "Horizon Blockchain Games", "license": "Apache-2.0", "scripts": { - "build": "forge build" + "build": "forge build", + "lint:init": "husky install", + "lint:sol": "forge fmt" }, "files": [ "src", @@ -23,5 +25,12 @@ "@0xsequence/erc-1155": "^4.0.1", "@0xsequence/erc20-meta-token": "^4.0.1", "erc721a": "^4.2.3" + }, + "lint-staged": { + "**/*.sol": "yarn lint:sol" + }, + "devDependencies": { + "husky": "^8.0.3", + "lint-staged": "^13.2.2" } } diff --git a/test/Counter.t.sol b/test/Counter.t.sol index fc5accfd..30235e8a 100644 --- a/test/Counter.t.sol +++ b/test/Counter.t.sol @@ -6,9 +6,10 @@ import "../src/Counter.sol"; contract CounterTest is Test { Counter public counter; + function setUp() public { - counter = new Counter(); - counter.setNumber(0); + counter = new Counter(); + counter.setNumber(0); } function testIncrement() public { diff --git a/yarn.lock b/yarn.lock index 334f784e..538974f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -365,6 +365,48 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + bech32@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -380,11 +422,94 @@ bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +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== + dependencies: + fill-range "^7.0.1" + brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.19: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + elliptic@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -398,6 +523,16 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + erc721a@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/erc721a/-/erc721a-4.2.3.tgz#ca6469b0e54afb0f614272c2147dc4cb49ff223f" @@ -439,6 +574,33 @@ ethers@^5.7.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +execa@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -456,16 +618,127 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +husky@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== +lilconfig@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lint-staged@^13.2.2: + version "13.2.2" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" + integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== + dependencies: + chalk "5.2.0" + cli-truncate "^3.1.0" + commander "^10.0.0" + debug "^4.3.4" + execa "^7.0.0" + lilconfig "2.1.0" + listr2 "^5.0.7" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-inspect "^1.12.3" + pidtree "^0.6.0" + string-argv "^0.3.1" + yaml "^2.2.2" + +listr2@^5.0.7: + version "5.0.8" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" + integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.19" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.8.0" + through "^2.3.8" + wrap-ansi "^7.0.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@^4.0.5: + 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" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -476,12 +749,232 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + +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== + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + scrypt-js@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +string-argv@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +yaml@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073" + integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA== From 699e1b5e59a2580dfbdc1c03dac40aff7bcca71c Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Thu, 11 May 2023 07:50:06 +1200 Subject: [PATCH 03/15] Add build script --- foundry.toml | 2 + package.json | 8 ++- scripts/build.ts | 55 +++++++++++++++++++++ scripts/constants.ts | 5 ++ yarn.lock | 114 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 scripts/build.ts create mode 100644 scripts/constants.ts diff --git a/foundry.toml b/foundry.toml index dcfcb1d3..c8a7cb1d 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,3 +3,5 @@ src = 'src' out = 'out' libs = ['lib'] solc = "0.8.17" +via_ir = true +optimizer-runs = 20_000 diff --git a/package.json b/package.json index e7f5bc36..163f8971 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "author": "Horizon Blockchain Games", "license": "Apache-2.0", "scripts": { - "build": "forge build", + "build": "ts-node scripts/build.ts", + "test": "forge test", "lint:init": "husky install", "lint:sol": "forge fmt" }, @@ -30,7 +31,10 @@ "**/*.sol": "yarn lint:sol" }, "devDependencies": { + "@types/node": "^20.1.0", "husky": "^8.0.3", - "lint-staged": "^13.2.2" + "lint-staged": "^13.2.2", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" } } diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 00000000..a047eee9 --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,55 @@ +import { exec as execNonPromise } from 'child_process' +import { copyFile, mkdir, readFile, rmdir, writeFile } from 'fs/promises' +import { join } from 'path' +import util from 'util' +import { BUILD_DIR, DEPLOYABLE_CONTRACT_NAMES } from './constants' +const exec = util.promisify(execNonPromise) + +const main = async () => { + // Clean + await rmdir(BUILD_DIR, { recursive: true }) + + // Build with forge + console.log('Building contracts') + await exec('forge build') + console.log('Contracts built') + + await mkdir(BUILD_DIR, { recursive: true }) + + // Create the compiler input files + for (const solFile of DEPLOYABLE_CONTRACT_NAMES) { + const forgeOutputDir = `out/${solFile}.sol` + const compilerDetails = JSON.parse( + await readFile(join(forgeOutputDir, `${solFile}.metadata.json`), 'utf8'), + ) + + // Replace source urls with file contents + for (const sourceKey of Object.keys(compilerDetails.sources)) { + compilerDetails.sources[sourceKey].contents = await readFile( + join(sourceKey), + 'utf8', + ) + } + + // Write the compiler input file + await writeFile( + join(BUILD_DIR, `${solFile}.input.json`), + JSON.stringify(compilerDetails), + ) + + // Copy the compiler output too + await copyFile( + `${forgeOutputDir}/${solFile}.json`, + `${BUILD_DIR}/${solFile}.json`, + ) + } +} + +main() + .then(() => { + console.log('Done') + }) + .catch(err => { + console.error(err) + process.exit(1) + }) diff --git a/scripts/constants.ts b/scripts/constants.ts new file mode 100644 index 00000000..8f4826b3 --- /dev/null +++ b/scripts/constants.ts @@ -0,0 +1,5 @@ +export const BUILD_DIR = 'build' +export const DEPLOYABLE_CONTRACT_NAMES = [ + 'ERC1155SaleFactory', + 'ERC721SaleFactory', +] diff --git a/yarn.lock b/yarn.lock index 538974f0..2ce08dd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,6 +18,13 @@ dependencies: "@0xsequence/erc-1155" "^4.0.1" +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" @@ -360,6 +367,59 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@types/node@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.1.0.tgz#258805edc37c327cf706e64c6957f241ca4c4c20" + integrity sha512-O+z53uwx64xY7D6roOi4+jApDGFg0qn6WHcxe5QeqjMaTezBO/mxdfFXIVAVVyNWKx84OmPB3L8kbVYOTeN34A== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" @@ -402,6 +462,11 @@ ansi-styles@^6.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -489,6 +554,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -505,6 +575,11 @@ debug@^4.3.4: dependencies: ms "2.1.2" +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -716,6 +791,11 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -934,6 +1014,25 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tslib@^2.1.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" @@ -944,6 +1043,16 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +typescript@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -978,3 +1087,8 @@ yaml@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073" integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 098bd645b348d5dfa4c039782e2fe50ba1da8dcd Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Tue, 2 May 2023 10:32:18 +1200 Subject: [PATCH 04/15] Base token implementations --- package.json | 6 +- remappings.txt | 3 + script/Counter.s.sol | 12 - src/Counter.sol | 14 - src/proxies/ERC1967/IERC1967.sol | 8 + src/proxies/ERC1967/Proxy.sol | 62 ++++ src/proxies/ERC1967/ProxyDeployer.sol | 72 ++++ src/proxies/ERC1967/ProxyDeployerErrors.sol | 10 + src/tokens/ERC1155/ERC1155Token.sol | 147 ++++++++ src/tokens/ERC1155/ERC1155TokenFactory.sol | 36 ++ src/tokens/ERC1155/IERC1155TokenFactory.sol | 22 ++ .../ERC1155/Packed/ERC1155PackedToken.sol | 153 +++++++++ .../Packed/ERC1155PackedTokenFactory.sol | 36 ++ .../Packed/IERC1155PackedTokenFactory.sol | 22 ++ src/tokens/ERC721/ERC721Token.sol | 154 +++++++++ src/tokens/ERC721/ERC721TokenFactory.sol | 37 ++ src/tokens/ERC721/IERC721TokenFactory.sol | 23 ++ src/utils/StorageSlot.sol | 64 ++++ test/Counter.t.sol | 24 -- test/tokens/ERC1155/ERC1155Token.t.sol | 319 ++++++++++++++++++ .../ERC1155/Packed/ERC1155PackedToken.t.sol | 312 +++++++++++++++++ test/tokens/ERC721/ERC721Token.t.sol | 265 +++++++++++++++ yarn.lock | 23 ++ 23 files changed, 1772 insertions(+), 52 deletions(-) delete mode 100644 script/Counter.s.sol delete mode 100644 src/Counter.sol create mode 100644 src/proxies/ERC1967/IERC1967.sol create mode 100644 src/proxies/ERC1967/Proxy.sol create mode 100644 src/proxies/ERC1967/ProxyDeployer.sol create mode 100644 src/proxies/ERC1967/ProxyDeployerErrors.sol create mode 100644 src/tokens/ERC1155/ERC1155Token.sol create mode 100644 src/tokens/ERC1155/ERC1155TokenFactory.sol create mode 100644 src/tokens/ERC1155/IERC1155TokenFactory.sol create mode 100644 src/tokens/ERC1155/Packed/ERC1155PackedToken.sol create mode 100644 src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol create mode 100644 src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol create mode 100644 src/tokens/ERC721/ERC721Token.sol create mode 100644 src/tokens/ERC721/ERC721TokenFactory.sol create mode 100644 src/tokens/ERC721/IERC721TokenFactory.sol create mode 100644 src/utils/StorageSlot.sol delete mode 100644 test/Counter.t.sol create mode 100644 test/tokens/ERC1155/ERC1155Token.t.sol create mode 100644 test/tokens/ERC1155/Packed/ERC1155PackedToken.t.sol create mode 100644 test/tokens/ERC721/ERC721Token.t.sol diff --git a/package.json b/package.json index 163f8971..8506b7de 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,11 @@ "dist" ], "dependencies": { - "@0xsequence/erc-1155": "^4.0.1", + "@0xsequence/erc-1155": "^4.0.3", "@0xsequence/erc20-meta-token": "^4.0.1", - "erc721a": "^4.2.3" + "@openzeppelin/contracts": "^4.8.3", + "erc721a": "^4.2.3", + "erc721a-upgradeable": "^4.2.3" }, "lint-staged": { "**/*.sol": "yarn lint:sol" diff --git a/remappings.txt b/remappings.txt index 17deda06..85048852 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,3 +2,6 @@ ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ @0xsequence/erc20-meta-token/=node_modules/@0xsequence/erc20-meta-token/ @0xsequence/erc-1155/=node_modules/@0xsequence/erc-1155/ +erc721a/=node_modules/erc721a/ +erc721a-upgradeable/=node_modules/erc721a-upgradeable/ +@openzeppelin/=node_modules/@openzeppelin/ diff --git a/script/Counter.s.sol b/script/Counter.s.sol deleted file mode 100644 index 0e546aba..00000000 --- a/script/Counter.s.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Script.sol"; - -contract CounterScript is Script { - function setUp() public {} - - function run() public { - vm.broadcast(); - } -} diff --git a/src/Counter.sol b/src/Counter.sol deleted file mode 100644 index aded7997..00000000 --- a/src/Counter.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } - - function increment() public { - number++; - } -} diff --git a/src/proxies/ERC1967/IERC1967.sol b/src/proxies/ERC1967/IERC1967.sol new file mode 100644 index 00000000..058f89be --- /dev/null +++ b/src/proxies/ERC1967/IERC1967.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +interface IERC1967 { + event Upgraded(address indexed implementation); + event AdminChanged(address previousAdmin, address newAdmin); + event BeaconUpgraded(address indexed beacon); +} diff --git a/src/proxies/ERC1967/Proxy.sol b/src/proxies/ERC1967/Proxy.sol new file mode 100644 index 00000000..833e49ef --- /dev/null +++ b/src/proxies/ERC1967/Proxy.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {IERC1967} from "./IERC1967.sol"; +import {StorageSlot} from "../../utils/StorageSlot.sol"; + +contract Proxy is IERC1967 { + bytes32 internal constant _IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); + + /** + * Initializes the contract, setting proxy implementation address. + */ + constructor(address _implementation) { + _setImplementation(_implementation); + emit Upgraded(_implementation); + } + + /** + * Forward calls to the proxy implementation contract. + */ + receive() external payable { + proxy(); + } + + /** + * Forward calls to the proxy implementation contract. + */ + fallback() external payable { + proxy(); + } + + /** + * Forward calls to the proxy implementation contract. + */ + function proxy() private { + address target = _getImplementation(); + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, 0, calldatasize()) + let result := delegatecall(gas(), target, ptr, calldatasize(), 0, 0) + let size := returndatasize() + returndatacopy(ptr, 0, size) + switch result + case 0 { revert(ptr, size) } + default { return(ptr, size) } + } + } + + /** + * Set the implementation address. + */ + function _setImplementation(address _implementation) internal { + StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = _implementation; + } + + /** + * Returns the address of the current implementation. + */ + function _getImplementation() internal view returns (address) { + return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + } +} diff --git a/src/proxies/ERC1967/ProxyDeployer.sol b/src/proxies/ERC1967/ProxyDeployer.sol new file mode 100644 index 00000000..a61f8a63 --- /dev/null +++ b/src/proxies/ERC1967/ProxyDeployer.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ProxyDeployerErrors} from "./ProxyDeployerErrors.sol"; +import {Proxy} from "./Proxy.sol"; + +abstract contract ProxyDeployer is ProxyDeployerErrors { + /** + * Creates a proxy contract for a given implementation + * @param implAddr The address of the proxy implementation + * @param salt The deployment salt + * @return proxyAddr The address of the deployed proxy + */ + function _deployProxy(address implAddr, bytes32 salt) internal returns (address proxyAddr) { + bytes memory code = _getProxyCode(implAddr); + + // Deploy it + assembly { + proxyAddr := create2(0, add(code, 32), mload(code), salt) + } + if (proxyAddr == address(0)) { + revert ProxyCreationFailed(); + } + return proxyAddr; + } + + /** + * Predict the deployed wrapper proxy address for a given implementation. + * @param implAddr The address of the proxy implementation + * @param salt The deployment salt + * @return proxyAddr The address of the deployed wrapper + */ + function predictProxyAddress(address implAddr, bytes32 salt) public view returns (address proxyAddr) { + bytes memory code = _getProxyCode(implAddr); + return _predictProxyAddress(code, salt); + } + + /** + * Predict the deployed wrapper proxy address for a given implementation. + * @param code The code of the wrapper implementation + * @param salt The deployment salt + * @return proxyAddr The address of the deployed wrapper + */ + function _predictProxyAddress(bytes memory code, bytes32 salt) private view returns (address proxyAddr) { + address deployer = address(this); + bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(code))); + return address(uint160(uint256(_data))); + } + + /** + * Returns the code of the proxy contract for a given implementation + * @param implAddr The address of the proxy implementation + * @return code The code of the proxy contract + */ + function _getProxyCode(address implAddr) private pure returns (bytes memory code) { + return abi.encodePacked(type(Proxy).creationCode, abi.encode(implAddr)); + } + + /** + * Checks if an address is a contract + * @param addr The address to check + * @return result True if the address is a contract + */ + function _isContract(address addr) internal view returns (bool result) { + uint256 csize; + // solhint-disable-next-line no-inline-assembly + assembly { + csize := extcodesize(addr) + } + return csize != 0; + } +} diff --git a/src/proxies/ERC1967/ProxyDeployerErrors.sol b/src/proxies/ERC1967/ProxyDeployerErrors.sol new file mode 100644 index 00000000..cdab2c9f --- /dev/null +++ b/src/proxies/ERC1967/ProxyDeployerErrors.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +/** + * Errors for the Proxy Deployer contract. + */ +abstract contract ProxyDeployerErrors { + // Factories + error ProxyCreationFailed(); +} diff --git a/src/tokens/ERC1155/ERC1155Token.sol b/src/tokens/ERC1155/ERC1155Token.sol new file mode 100644 index 00000000..f81ed5c5 --- /dev/null +++ b/src/tokens/ERC1155/ERC1155Token.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC1155, ERC1155MintBurn} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155MintBurn.sol"; +import {ERC1155Meta} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Meta.sol"; +import {ERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +error InvalidInitialization(); + +/** + * A ready made implementation of ERC-1155. + */ +contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981, AccessControl { + bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); + + address private immutable _initializer; + bool private _initialized; + + /** + * Initialize contract. + */ + constructor() ERC1155Metadata("", "") { + _initializer = msg.sender; + } + + /** + * Initialize the contract. + * @param _owner Owner address. + * @param _name Token name. + * @param _baseURI Base URI for token metadata. + * @dev This should be called immediately after deployment. + */ + function initialize(address _owner, string memory _name, string memory _baseURI) public { + if (msg.sender != _initializer || _initialized) { + revert InvalidInitialization(); + } + _initialized = true; + + name = _name; + baseURI = _baseURI; + + _setupRole(DEFAULT_ADMIN_ROLE, _owner); + _setupRole(MINTER_ROLE, _owner); + _setupRole(ROYALTY_ADMIN_ROLE, _owner); + _setupRole(METADATA_ADMIN_ROLE, _owner); + } + + // + // Minting + // + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _tokenId Token ID to mint. + * @param _amount Amount of tokens to mint. + * @param _data Data to pass if receiver is contract. + */ + function mint(address _to, uint256 _tokenId, uint256 _amount, bytes memory _data) external onlyRole(MINTER_ROLE) { + _mint(_to, _tokenId, _amount, _data); + } + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _tokenIds Token IDs to mint. + * @param _amounts Amounts of tokens to mint. + * @param _data Data to pass if receiver is contract. + */ + function batchMint(address _to, uint256[] memory _tokenIds, uint256[] memory _amounts, bytes memory _data) + external + onlyRole(MINTER_ROLE) + { + _batchMint(_to, _tokenIds, _amounts, _data); + } + + // + // Royalty + // + + /** + * Sets the royalty information that all ids in this contract will default to. + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + */ + function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { + _setDefaultRoyalty(_receiver, _feeNumerator); + } + + /** + * Sets the royalty information that a given token id in this contract will use. + * @param _tokenId The token id to set the royalty information for + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @notice This overrides the default royalty information for this token id + */ + function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) + external + onlyRole(ROYALTY_ADMIN_ROLE) + { + _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); + } + + // + // Metadata + // + + /** + * Update the base URL of token's URI. + * @param _baseMetadataURI New base URL of token's URI + */ + function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(_baseMetadataURI); + } + + /** + * Update the name of the contract. + * @param _name New contract name + */ + function setContractName(string memory _name) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(_name); + } + + // + // Views + // + + /** + * Check interface support. + * @param _interfaceId Interface id + * @return True if supported + */ + function supportsInterface(bytes4 _interfaceId) + public + view + override (ERC1155, ERC1155Metadata, ERC2981, AccessControl) + returns (bool) + { + return ERC1155.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) + || ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) + || super.supportsInterface(_interfaceId); + } +} diff --git a/src/tokens/ERC1155/ERC1155TokenFactory.sol b/src/tokens/ERC1155/ERC1155TokenFactory.sol new file mode 100644 index 00000000..850f559c --- /dev/null +++ b/src/tokens/ERC1155/ERC1155TokenFactory.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC1155Token} from "./ERC1155Token.sol"; +import {IERC1155TokenFactory} from "./IERC1155TokenFactory.sol"; +import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; + +contract ERC1155TokenFactory is IERC1155TokenFactory, ProxyDeployer { + address private immutable _implAddr; + + /** + * Creates an ERC-1155 Token Factory. + */ + constructor() { + ERC1155Token proxyImpl = new ERC1155Token(); + _implAddr = address(proxyImpl); + } + + /** + * Creates an ERC-1155 Token proxy. + * @param _owner The owner of the ERC-1155 Token proxy + * @param _name The name of the ERC-1155 Token proxy + * @param _baseURI The base URI of the ERC-1155 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-1155 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr) + { + proxyAddr = _deployProxy(_implAddr, _salt); + ERC1155Token(proxyAddr).initialize(_owner, _name, _baseURI); + emit ERC1155TokenDeployed(proxyAddr); + return proxyAddr; + } +} diff --git a/src/tokens/ERC1155/IERC1155TokenFactory.sol b/src/tokens/ERC1155/IERC1155TokenFactory.sol new file mode 100644 index 00000000..23b79a0a --- /dev/null +++ b/src/tokens/ERC1155/IERC1155TokenFactory.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +interface IERC1155TokenFactory { + /** + * Event emitted when a new ERC-1155 Token proxy contract is deployed. + * @param proxyAddr The address of the deployed proxy. + */ + event ERC1155TokenDeployed(address proxyAddr); + + /** + * Creates an ERC-1155 Token proxy. + * @param _owner The owner of the ERC-1155 Token proxy + * @param _name The name of the ERC-1155 Token proxy + * @param _baseURI The base URI of the ERC-1155 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-1155 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr); +} diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol new file mode 100644 index 00000000..1a41db1b --- /dev/null +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import { + ERC1155PackedBalance, + ERC1155MintBurnPackedBalance +} from "@0xsequence/erc-1155/contracts/tokens/ERC1155PackedBalance/ERC1155MintBurnPackedBalance.sol"; +import {ERC1155MetaPackedBalance} from + "@0xsequence/erc-1155/contracts/tokens/ERC1155PackedBalance/ERC1155MetaPackedBalance.sol"; +import {ERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +error InvalidInitialization(); + +/** + * A ready made implementation of ERC-1155. + */ +contract ERC1155PackedToken is + ERC1155MintBurnPackedBalance, + ERC1155MetaPackedBalance, + ERC1155Metadata, + ERC2981, + AccessControl +{ + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); + bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); + + bool private _initialized; + + /** + * Initialize contract. + */ + constructor() ERC1155Metadata("", "") {} + + /** + * Initialize the contract. + * @param _owner Owner address. + * @param _name Token name. + * @param _baseURI Base URI for token metadata. + * @dev This should be called immediately after deployment. + */ + function initialize(address _owner, string memory _name, string memory _baseURI) public { + if (_initialized) { + revert InvalidInitialization(); + } + _initialized = true; + name = _name; + baseURI = _baseURI; + + _setupRole(DEFAULT_ADMIN_ROLE, _owner); + _setupRole(MINTER_ROLE, _owner); + _setupRole(ROYALTY_ADMIN_ROLE, _owner); + _setupRole(METADATA_ADMIN_ROLE, _owner); + } + + // + // Minting + // + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _tokenId Token ID to mint. + * @param _amount Amount of tokens to mint. + * @param _data Data to pass if receiver is contract. + */ + function mint(address _to, uint256 _tokenId, uint256 _amount, bytes memory _data) external onlyRole(MINTER_ROLE) { + _mint(_to, _tokenId, _amount, _data); + } + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _tokenIds Token IDs to mint. + * @param _amounts Amounts of tokens to mint. + * @param _data Data to pass if receiver is contract. + */ + function batchMint(address _to, uint256[] memory _tokenIds, uint256[] memory _amounts, bytes memory _data) + external + onlyRole(MINTER_ROLE) + { + _batchMint(_to, _tokenIds, _amounts, _data); + } + + // + // Royalty + // + + /** + * Sets the royalty information that all ids in this contract will default to. + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + */ + function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { + _setDefaultRoyalty(_receiver, _feeNumerator); + } + + /** + * Sets the royalty information that a given token id in this contract will use. + * @param _tokenId The token id to set the royalty information for + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @notice This overrides the default royalty information for this token id + */ + function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) + external + onlyRole(ROYALTY_ADMIN_ROLE) + { + _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); + } + + // + // Metadata + // + + /** + * Update the base URL of token's URI. + * @param _baseMetadataURI New base URL of token's URI + */ + function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(_baseMetadataURI); + } + + /** + * Update the name of the contract. + * @param _name New contract name + */ + function setContractName(string memory _name) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(_name); + } + + // + // Views + // + + /** + * Check interface support. + * @param _interfaceId Interface id + * @return True if supported + */ + function supportsInterface(bytes4 _interfaceId) + public + view + override (ERC1155PackedBalance, ERC1155Metadata, ERC2981, AccessControl) + returns (bool) + { + return ERC1155PackedBalance.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) + || ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) + || super.supportsInterface(_interfaceId); + } +} diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol new file mode 100644 index 00000000..f10dd9ca --- /dev/null +++ b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC1155PackedToken} from "./ERC1155PackedToken.sol"; +import {IERC1155PackedTokenFactory} from "./IERC1155PackedTokenFactory.sol"; +import {ProxyDeployer} from "../../../proxies/ERC1967/ProxyDeployer.sol"; + +contract ERC1155PackedTokenFactory is IERC1155PackedTokenFactory, ProxyDeployer { + address private immutable _implAddr; + + /** + * Creates an ERC-1155 Token Factory. + */ + constructor() { + ERC1155PackedToken proxyImpl = new ERC1155PackedToken(); + _implAddr = address(proxyImpl); + } + + /** + * Creates an ERC-1155 Packed Token proxy. + * @param _owner The owner of the ERC-1155 Packed Token proxy + * @param _name The name of the ERC-1155 Packed Token proxy + * @param _baseURI The base URI of the ERC-1155 Packed Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-1155 Packed Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr) + { + proxyAddr = _deployProxy(_implAddr, _salt); + ERC1155PackedToken(proxyAddr).initialize(_owner, _name, _baseURI); + emit ERC1155PackedTokenDeployed(proxyAddr); + return proxyAddr; + } +} diff --git a/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol new file mode 100644 index 00000000..e4f7ef12 --- /dev/null +++ b/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +interface IERC1155PackedTokenFactory { + /** + * Event emitted when a new ERC-1155 Packed Token proxy contract is deployed. + * @param proxyAddr The address of the deployed proxy. + */ + event ERC1155PackedTokenDeployed(address proxyAddr); + + /** + * Creates an ERC-1155 Packed Token proxy. + * @param _owner The owner of the ERC-1155 Packed Token proxy + * @param _name The name of the ERC-1155 Packed Token proxy + * @param _baseURI The base URI of the ERC-1155 Packed Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-1155 Packed Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr); +} diff --git a/src/tokens/ERC721/ERC721Token.sol b/src/tokens/ERC721/ERC721Token.sol new file mode 100644 index 00000000..934637b7 --- /dev/null +++ b/src/tokens/ERC721/ERC721Token.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import { + ERC721AQueryable, IERC721AQueryable, ERC721A, IERC721A +} from "erc721a/contracts/extensions/ERC721AQueryable.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +error InvalidInitialization(); + +/** + * A ready made implementation of ERC-721. + */ +contract ERC721Token is ERC721AQueryable, ERC2981, AccessControl { + bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); + + string private baseURI; // Missing _ due to _baseURI() function in ERC721A + string private _name; + string private _symbol; + + address private immutable _initializer; + bool private _initialized; + + /** + * Deploy contract. + */ + constructor() ERC721A("", "") { + _initializer = msg.sender; + } + + /** + * Initialize contract. + * @param owner_ The owner of the contract + * @param name_ Name of the token + * @param symbol_ Symbol of the token + * @param baseURI_ Base URI of the token + * @dev This should be called immediately after deployment. + */ + function initialize(address owner_, string memory name_, string memory symbol_, string memory baseURI_) external { + if (msg.sender != _initializer || _initialized) { + revert InvalidInitialization(); + } + _initialized = true; + + _name = name_; + _symbol = symbol_; + baseURI = baseURI_; + + _setupRole(DEFAULT_ADMIN_ROLE, owner_); + _setupRole(METADATA_ADMIN_ROLE, owner_); + _setupRole(MINTER_ROLE, owner_); + _setupRole(ROYALTY_ADMIN_ROLE, owner_); + } + + // + // Minting + // + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _amount Amount of tokens to mint. + */ + function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) { + _mint(_to, _amount); + } + + // + // Royalty + // + + /** + * Sets the royalty information that all ids in this contract will default to. + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + */ + function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { + _setDefaultRoyalty(_receiver, _feeNumerator); + } + + /** + * Sets the royalty information that a given token id in this contract will use. + * @param _tokenId The token id to set the royalty information for + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @notice This overrides the default royalty information for this token id + */ + function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) + external + onlyRole(ROYALTY_ADMIN_ROLE) + { + _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); + } + + // + // Metadata + // + + /** + * Update the base URL of token's URI. + * @param _baseMetadataURI New base URL of token's URI + */ + function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { + baseURI = _baseMetadataURI; + } + + // + // Views + // + + /** + * Check interface support. + * @param _interfaceId Interface id + * @return True if supported + */ + function supportsInterface(bytes4 _interfaceId) + public + view + override (ERC721A, IERC721A, ERC2981, AccessControl) + returns (bool) + { + return _interfaceId == type(IERC721A).interfaceId || _interfaceId == type(IERC721AQueryable).interfaceId + || ERC721A.supportsInterface(_interfaceId) || ERC2981.supportsInterface(_interfaceId) + || AccessControl.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); + } + + // + // ERC721A Overrides + // + + /** + * Override the ERC721A baseURI function. + */ + function _baseURI() internal view override returns (string memory) { + return baseURI; + } + + /** + * Override the ERC721A name function. + */ + function name() public view override (ERC721A, IERC721A) returns (string memory) { + return _name; + } + + /** + * Override the ERC721A name function. + */ + function symbol() public view override (ERC721A, IERC721A) returns (string memory) { + return _symbol; + } +} diff --git a/src/tokens/ERC721/ERC721TokenFactory.sol b/src/tokens/ERC721/ERC721TokenFactory.sol new file mode 100644 index 00000000..ff20e99a --- /dev/null +++ b/src/tokens/ERC721/ERC721TokenFactory.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC721Token} from "./ERC721Token.sol"; +import {IERC721TokenFactory} from "./IERC721TokenFactory.sol"; +import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; + +contract ERC721TokenFactory is IERC721TokenFactory, ProxyDeployer { + address private immutable _implAddr; + + /** + * Creates an ERC-721 Token Factory. + */ + constructor() { + ERC721Token proxyImpl = new ERC721Token(); + _implAddr = address(proxyImpl); + } + + /** + * Creates an ERC-721 Token proxy. + * @param _owner The owner of the ERC-721 Token proxy + * @param _name The name of the ERC-721 Token proxy + * @param _symbol The symbol of the ERC-721 Token proxy + * @param _baseURI The base URI of the ERC-721 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-721 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _symbol, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr) + { + proxyAddr = _deployProxy(_implAddr, _salt); + ERC721Token(proxyAddr).initialize(_owner, _name, _symbol, _baseURI); + emit ERC721TokenDeployed(proxyAddr); + return proxyAddr; + } +} diff --git a/src/tokens/ERC721/IERC721TokenFactory.sol b/src/tokens/ERC721/IERC721TokenFactory.sol new file mode 100644 index 00000000..ed78642b --- /dev/null +++ b/src/tokens/ERC721/IERC721TokenFactory.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +interface IERC721TokenFactory { + /** + * Event emitted when a new ERC-721 Token proxy contract is deployed. + * @param proxyAddr The address of the deployed proxy. + */ + event ERC721TokenDeployed(address proxyAddr); + + /** + * Creates an ERC-721 Token proxy. + * @param _owner The owner of the ERC-721 Token proxy + * @param _name The name of the ERC-721 Token proxy + * @param _symbol The symbol of the ERC-721 Token proxy + * @param _baseURI The base URI of the ERC-721 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-721 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _symbol, string memory _baseURI, bytes32 _salt) + external + returns (address proxyAddr); +} diff --git a/src/utils/StorageSlot.sol b/src/utils/StorageSlot.sol new file mode 100644 index 00000000..775a4b6b --- /dev/null +++ b/src/utils/StorageSlot.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +/** + * @dev Library for reading and writing primitive types to specific storage slots. + * + * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. + */ +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + assembly { + r.slot := slot + } + } +} diff --git a/test/Counter.t.sol b/test/Counter.t.sol deleted file mode 100644 index 30235e8a..00000000 --- a/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; -import "../src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function testIncrement() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testSetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } -} diff --git a/test/tokens/ERC1155/ERC1155Token.t.sol b/test/tokens/ERC1155/ERC1155Token.t.sol new file mode 100644 index 00000000..9b6b84aa --- /dev/null +++ b/test/tokens/ERC1155/ERC1155Token.t.sol @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import "forge-std/Test.sol"; +import {ERC1155Token, InvalidInitialization} from "src/tokens/ERC1155/ERC1155Token.sol"; +import {ERC1155TokenFactory} from "src/tokens/ERC1155/ERC1155TokenFactory.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +// Interfaces +import {IERC165} from "@0xsequence/erc-1155/contracts/interfaces/IERC165.sol"; +import {IERC1155} from "@0xsequence/erc-1155/contracts/interfaces/IERC1155.sol"; +import {IERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; + +contract ERC1155TokenTest is Test { + // Redeclare events + event TransferSingle( + address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount + ); + event TransferBatch( + address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts + ); + + ERC1155Token private token; + + address owner; + + function setUp() public { + owner = makeAddr("owner"); + + vm.deal(address(this), 100 ether); + vm.deal(owner, 100 ether); + + ERC1155TokenFactory factory = new ERC1155TokenFactory(); + token = ERC1155Token(factory.deploy(owner, "name", "baseURI", 0x0)); + } + + function testReinitializeFails() public { + vm.expectRevert(InvalidInitialization.selector); + token.initialize(owner, "name", "baseURI"); + } + + function testSupportsInterface() public { + assertTrue(token.supportsInterface(type(IERC165).interfaceId)); + assertTrue(token.supportsInterface(type(IERC1155).interfaceId)); + assertTrue(token.supportsInterface(type(IERC1155Metadata).interfaceId)); + } + + function testOwnerHasRoles() public { + assertTrue(token.hasRole(token.DEFAULT_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.METADATA_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.MINTER_ROLE(), owner)); + assertTrue(token.hasRole(token.ROYALTY_ADMIN_ROLE(), owner)); + } + + // + // Minting + // + function testMintInvalidRole(address caller) public { + vm.assume(caller != owner); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.mint(caller, 1, 1, ""); + + uint256[] memory tokenIds = new uint256[](1); + tokenIds[0] = 1; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.batchMint(caller, tokenIds, amounts, ""); + } + + function testMintOwner(uint256 tokenId, uint256 amount) public { + vm.assume(amount > 0); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferSingle(owner, address(0), owner, tokenId, amount); + vm.prank(owner); + token.mint(owner, tokenId, amount, ""); + + assertEq(token.balanceOf(owner, tokenId), amount); + } + + function testBatchMintOwner(uint256[] memory tokenIds, uint256[] memory amounts) public { + tokenIds = boundArrayLength(tokenIds, 10); + amounts = boundArrayLength(amounts, 10); + vm.assume(tokenIds.length == amounts.length); + for (uint256 i; i < amounts.length; i++) { + vm.assume(amounts[i] > 0); + } + // Unique ids + for (uint256 i; i < tokenIds.length; i++) { + for (uint256 j; j < tokenIds.length; j++) { + if (i != j) { + vm.assume(tokenIds[i] != tokenIds[j]); + } + } + } + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferBatch(owner, address(0), owner, tokenIds, amounts); + vm.prank(owner); + token.batchMint(owner, tokenIds, amounts, ""); + } + + function testMintWithRole(address minter, uint256 tokenId, uint256 amount) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferSingle(minter, address(0), owner, tokenId, amount); + + vm.prank(minter); + token.mint(owner, tokenId, amount, ""); + + assertEq(token.balanceOf(owner, tokenId), amount); + } + + function testBatchMintWithRole(address minter, uint256[] memory tokenIds, uint256[] memory amounts) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + tokenIds = boundArrayLength(tokenIds, 10); + amounts = boundArrayLength(amounts, 10); + vm.assume(tokenIds.length == amounts.length); + for (uint256 i; i < amounts.length; i++) { + vm.assume(amounts[i] > 0); + } + // Unique ids + for (uint256 i; i < tokenIds.length; i++) { + for (uint256 j; j < tokenIds.length; j++) { + if (i != j) { + vm.assume(tokenIds[i] != tokenIds[j]); + } + } + } + + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferBatch(minter, address(0), owner, tokenIds, amounts); + vm.prank(minter); + token.batchMint(owner, tokenIds, amounts, ""); + } + + // + // Metadata + // + function testMetadataOwner() public { + vm.prank(owner); + token.setBaseMetadataURI("ipfs://newURI/"); + + assertEq(token.uri(0), "ipfs://newURI/0.json"); + assertEq(token.uri(1), "ipfs://newURI/1.json"); + } + + function testMetadataInvalid(address caller) public { + vm.assume(caller != owner); + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.METADATA_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + function testMetadataWithRole(address caller) public { + vm.assume(caller != owner); + vm.assume(caller != address(0)); + // Give role + vm.startPrank(owner); + token.grantRole(token.METADATA_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + // + // Royalty + // + function testDefaultRoyalty(address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(tokenId != 69); // Other token id for default validation + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + (receiver_, amount) = token.royaltyInfo(69, salePrice); + assertEq(receiver_, address(0)); + assertEq(amount, 0); + } + + function testRoyaltyWithRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.startPrank(owner); + token.grantRole(token.ROYALTY_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (receiver_, amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testRoyaltyInvalidRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + } + + function boundArrayLength(uint256[] memory arr, uint256 maxSize) private pure returns (uint256[] memory) { + if (arr.length <= maxSize) { + return arr; + } + uint256[] memory result = new uint256[](maxSize); + for (uint256 i; i < maxSize; i++) { + result[i] = arr[i]; + } + return result; + } +} diff --git a/test/tokens/ERC1155/Packed/ERC1155PackedToken.t.sol b/test/tokens/ERC1155/Packed/ERC1155PackedToken.t.sol new file mode 100644 index 00000000..6a8e4c2d --- /dev/null +++ b/test/tokens/ERC1155/Packed/ERC1155PackedToken.t.sol @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import "forge-std/Test.sol"; +import {ERC1155PackedToken, InvalidInitialization} from "src/tokens/ERC1155/Packed/ERC1155PackedToken.sol"; +import {ERC1155PackedTokenFactory} from "src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +// Interfaces +import {IERC165} from "@0xsequence/erc-1155/contracts/interfaces/IERC165.sol"; +import {IERC1155} from "@0xsequence/erc-1155/contracts/interfaces/IERC1155.sol"; +import {IERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; + +contract ERC1155TokenTest is Test { + // Redeclare events + event TransferSingle( + address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount + ); + event TransferBatch( + address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts + ); + + ERC1155PackedToken private token; + + address owner; + + function setUp() public { + owner = makeAddr("owner"); + + vm.deal(address(this), 100 ether); + vm.deal(owner, 100 ether); + + ERC1155PackedTokenFactory factory = new ERC1155PackedTokenFactory(); + token = ERC1155PackedToken(factory.deploy(owner, "name", "baseURI", 0x0)); + } + + function testReinitializeFails() public { + vm.expectRevert(InvalidInitialization.selector); + token.initialize(owner, "name", "baseURI"); + } + + function testSupportsInterface() public { + assertTrue(token.supportsInterface(type(IERC165).interfaceId)); + assertTrue(token.supportsInterface(type(IERC1155).interfaceId)); + assertTrue(token.supportsInterface(type(IERC1155Metadata).interfaceId)); + } + + function testOwnerHasRoles() public { + assertTrue(token.hasRole(token.DEFAULT_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.METADATA_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.MINTER_ROLE(), owner)); + assertTrue(token.hasRole(token.ROYALTY_ADMIN_ROLE(), owner)); + } + + // + // Minting + // + function testMintInvalidRole(address caller) public { + vm.assume(caller != owner); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.mint(caller, 1, 1, ""); + + uint256[] memory tokenIds = new uint256[](1); + tokenIds[0] = 1; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1; + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.batchMint(caller, tokenIds, amounts, ""); + } + + function testMintOwner(uint256 tokenId, uint256 amount) public { + vm.assume(amount > 0 && amount < 2 ** 16); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferSingle(owner, address(0), owner, tokenId, amount); + vm.prank(owner); + token.mint(owner, tokenId, amount, ""); + + assertEq(token.balanceOf(owner, tokenId), amount); + } + + function testBatchMintOwner(uint256[] memory tokenIds, uint256[] memory amounts) public { + tokenIds = boundArrayLength(tokenIds, 10); + amounts = boundArrayLength(amounts, 10); + vm.assume(tokenIds.length == amounts.length); + for (uint256 i; i < amounts.length; i++) { + amounts[i] = _bound(amounts[i], 1, 2 ** 16); + } + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferBatch(owner, address(0), owner, tokenIds, amounts); + vm.prank(owner); + token.batchMint(owner, tokenIds, amounts, ""); + } + + function testMintWithRole(address minter, uint256 tokenId, uint256 amount) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + vm.assume(amount > 0 && amount < 2 ** 16); + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferSingle(minter, address(0), owner, tokenId, amount); + + vm.prank(minter); + token.mint(owner, tokenId, amount, ""); + + assertEq(token.balanceOf(owner, tokenId), amount); + } + + function testBatchMintWithRole(address minter, uint256[] memory tokenIds, uint256[] memory amounts) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + tokenIds = boundArrayLength(tokenIds, 10); + amounts = boundArrayLength(amounts, 10); + vm.assume(tokenIds.length == amounts.length); + for (uint256 i; i < amounts.length; i++) { + amounts[i] = _bound(amounts[i], 1, 2 ** 16); + } + // Unique ids + for (uint256 i; i < tokenIds.length; i++) { + for (uint256 j; j < tokenIds.length; j++) { + if (i != j) { + vm.assume(tokenIds[i] != tokenIds[j]); + } + } + } + + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, true, address(token)); + emit TransferBatch(minter, address(0), owner, tokenIds, amounts); + vm.prank(minter); + token.batchMint(owner, tokenIds, amounts, ""); + } + + // + // Metadata + // + function testMetadataOwner() public { + vm.prank(owner); + token.setBaseMetadataURI("ipfs://newURI/"); + + assertEq(token.uri(0), "ipfs://newURI/0.json"); + assertEq(token.uri(1), "ipfs://newURI/1.json"); + } + + function testMetadataInvalid(address caller) public { + vm.assume(caller != owner); + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.METADATA_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + function testMetadataWithRole(address caller) public { + vm.assume(caller != owner); + vm.assume(caller != address(0)); + // Give role + vm.startPrank(owner); + token.grantRole(token.METADATA_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + // + // Royalty + // + function testDefaultRoyalty(address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(tokenId != 69); // Other token id for default validation + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + (receiver_, amount) = token.royaltyInfo(69, salePrice); + assertEq(receiver_, address(0)); + assertEq(amount, 0); + } + + function testRoyaltyWithRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.startPrank(owner); + token.grantRole(token.ROYALTY_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (receiver_, amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testRoyaltyInvalidRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + } + + function boundArrayLength(uint256[] memory arr, uint256 maxSize) private pure returns (uint256[] memory) { + if (arr.length <= maxSize) { + return arr; + } + uint256[] memory result = new uint256[](maxSize); + for (uint256 i; i < maxSize; i++) { + result[i] = arr[i]; + } + return result; + } +} diff --git a/test/tokens/ERC721/ERC721Token.t.sol b/test/tokens/ERC721/ERC721Token.t.sol new file mode 100644 index 00000000..a534dbed --- /dev/null +++ b/test/tokens/ERC721/ERC721Token.t.sol @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import "forge-std/Test.sol"; +import {ERC721Token, InvalidInitialization} from "src/tokens/ERC721/ERC721Token.sol"; +import {ERC721TokenFactory} from "src/tokens/ERC721/ERC721TokenFactory.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +// Interfaces +import {IERC165} from "@0xsequence/erc-1155/contracts/interfaces/IERC165.sol"; +import {IERC721A} from "erc721a/contracts/interfaces/IERC721A.sol"; +import {IERC721AQueryable} from "erc721a/contracts/extensions/IERC721AQueryable.sol"; + +contract ERC721TokenTest is Test { + // Redeclare events + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + + ERC721Token private token; + + address owner; + + function setUp() public { + owner = makeAddr("owner"); + + vm.deal(address(this), 100 ether); + vm.deal(owner, 100 ether); + + ERC721TokenFactory factory = new ERC721TokenFactory(); + token = ERC721Token(factory.deploy(owner, "name", "symbol", "baseURI", 0x0)); + } + + function testReinitializeFails() public { + vm.expectRevert(InvalidInitialization.selector); + token.initialize(owner, "name", "symbol", "baseURI"); + } + + function testSupportsInterface() public { + assertTrue(token.supportsInterface(type(IERC165).interfaceId)); + assertTrue(token.supportsInterface(type(IERC721A).interfaceId)); + assertTrue(token.supportsInterface(type(IERC721AQueryable).interfaceId)); + assertTrue(token.supportsInterface(0x80ac58cd)); // ERC721 + assertTrue(token.supportsInterface(0x5b5e139f)); // ERC721Metadata + } + + function testOwnerHasRoles() public { + assertTrue(token.hasRole(token.DEFAULT_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.METADATA_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.MINTER_ROLE(), owner)); + assertTrue(token.hasRole(token.ROYALTY_ADMIN_ROLE(), owner)); + } + + function testNameAndSymbol() public { + assertEq(token.name(), "name"); + assertEq(token.symbol(), "symbol"); + } + + // + // Minting + // + function testMintInvalidRole(address caller) public { + vm.assume(caller != owner); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.mint(caller, 1); + } + + function testMintOwner() public { + vm.expectEmit(true, true, true, true, address(token)); + emit Transfer(address(0), owner, 0); + + vm.prank(owner); + token.mint(owner, 1); + + assertEq(token.balanceOf(owner), 1); + } + + function testMintWithRole(address minter) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, true, address(token)); + emit Transfer(address(0), owner, 0); + + vm.prank(minter); + token.mint(owner, 1); + + assertEq(token.balanceOf(owner), 1); + } + + function testMintMultiple() public { + vm.expectEmit(true, true, true, true, address(token)); + emit Transfer(address(0), owner, 0); + vm.expectEmit(true, true, true, true, address(token)); + emit Transfer(address(0), owner, 1); + + vm.prank(owner); + token.mint(owner, 2); + + assertEq(token.balanceOf(owner), 2); + assertEq(token.ownerOf(0), owner); + assertEq(token.ownerOf(1), owner); + } + + // + // Metadata + // + function testMetadataOwner() public { + // Mint token + vm.prank(owner); + token.mint(owner, 2); + + vm.prank(owner); + token.setBaseMetadataURI("ipfs://newURI/"); + + assertEq(token.tokenURI(0), "ipfs://newURI/0"); + assertEq(token.tokenURI(1), "ipfs://newURI/1"); + + // Invalid token + vm.expectRevert(IERC721A.URIQueryForNonexistentToken.selector); + token.tokenURI(2); + } + + function testMetadataInvalid(address caller) public { + vm.assume(caller != owner); + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.METADATA_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + function testMetadataWithRole(address caller) public { + vm.assume(caller != owner); + vm.assume(caller != address(0)); + // Give role + vm.startPrank(owner); + token.grantRole(token.METADATA_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setBaseMetadataURI("ipfs://newURI/"); + } + + // + // Royalty + // + function testDefaultRoyalty(address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator, uint256 salePrice) public { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(tokenId != 69); // Other token id for default validation + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.prank(owner); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + (receiver_, amount) = token.royaltyInfo(69, salePrice); + assertEq(receiver_, address(0)); + assertEq(amount, 0); + } + + function testRoyaltyWithRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.startPrank(owner); + token.grantRole(token.ROYALTY_ADMIN_ROLE(), caller); + vm.stopPrank(); + + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + (address receiver_, uint256 amount) = token.royaltyInfo(1, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + + (receiver_, amount) = token.royaltyInfo(tokenId, salePrice); + assertEq(receiver_, receiver); + assertEq(amount, salePrice * feeNumerator / 10000); + } + + function testRoyaltyInvalidRole( + address caller, + uint256 tokenId, + address receiver, + uint96 feeNumerator, + uint256 salePrice + ) + public + { + vm.assume(feeNumerator <= 10000); + vm.assume(receiver != address(0)); + vm.assume(caller != owner); + vm.assume(salePrice < type(uint128).max); // Buffer for overflow + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setDefaultRoyalty(receiver, feeNumerator); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.ROYALTY_ADMIN_ROLE()), 32) + ) + ); + vm.prank(caller); + token.setTokenRoyalty(tokenId, receiver, feeNumerator); + } +} diff --git a/yarn.lock b/yarn.lock index 2ce08dd4..94dc5bf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11,6 +11,19 @@ "@ethersproject/providers" "^5.7.2" ethers "^5.7.2" +<<<<<<< HEAD +"@0xsequence/erc-1155@^4.0.2": +======= +"@0xsequence/erc-1155@^4.0.3": +>>>>>>> e4c96a7 (Base implementations) + version "4.0.3" + resolved "https://registry.yarnpkg.com/@0xsequence/erc-1155/-/erc-1155-4.0.3.tgz#b9b890c1ced04a84f36be22dd20424b43b9e1da2" + integrity sha512-vDh4OEuq0bR3iIqhsxpuRpczH5GxwH/mjBWm9uP6VYKnKM36ZBLApSNUlIOCXYRCS0DYFxsdvYjAemb3w1l4ow== + optionalDependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + ethers "^5.7.2" + "@0xsequence/erc20-meta-token@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@0xsequence/erc20-meta-token/-/erc20-meta-token-4.0.1.tgz#44fe77822af0ff3b1111466615c9958e92aca782" @@ -385,6 +398,11 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@openzeppelin/contracts@^4.8.3": + version "4.8.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" + integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -608,6 +626,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +erc721a-upgradeable@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/erc721a-upgradeable/-/erc721a-upgradeable-4.2.3.tgz#9e67a9d628f8648a0cd64d17a7a13eeba61deba1" + integrity sha512-EaHbOVDau9drDNpi/gWUHHaopCh35NMATa+3+9ZmdHokw9kfPiDD5RhGRlXA1aZA0ZfYvqPEbaKuSH3PaCY2Ug== + erc721a@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/erc721a/-/erc721a-4.2.3.tgz#ca6469b0e54afb0f614272c2147dc4cb49ff223f" From 214cbbb52a2bccd7b2f6e844c6d7aed431a03358 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 12:18:32 +1200 Subject: [PATCH 05/15] Add CI --- .github/workflows/ci.yaml | 96 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..c3f7000b --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,96 @@ + +on: [push] + +name: ci + +jobs: + install: + name: Install dependencies + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions/setup-node@v1 + with: + node-version: 18 + - uses: actions/cache@master + id: yarn-cache + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json', '**/yarn.lock') }} + - run: yarn install --network-concurrency 1 + if: ${{ steps.yarn-cache.outputs.cache-hit != 'true' }} + + lint-sol: + name: Solidity lint + runs-on: ubuntu-latest + needs: [install] + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions/setup-node@v1 + with: + node-version: 18 + - uses: actions/cache@master + id: yarn-cache + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json', '**/yarn.lock') }} + - run: yarn lint:sol + + foundry-tests: + name: Foundry tests + runs-on: ubuntu-latest + needs: [install] + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions/setup-node@v1 + with: + node-version: 18 + - uses: actions/cache@master + id: yarn-cache + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json', '**/yarn.lock') }} + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Run tests + run: FOUNDRY_FUZZ_RUNS=1024 forge test -vvv + + # coverage: + # name: Coverage + # runs-on: ubuntu-latest + # needs: [install] + # steps: + # - uses: actions/checkout@v3 + # with: + # submodules: recursive + # - uses: actions/setup-node@v1 + # with: + # node-version: 18 + # - uses: actions/cache@master + # id: yarn-cache + # with: + # path: | + # node_modules + # */*/node_modules + # key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json', '**/yarn.lock') }} + # - run: yarn coverage || true + # - name: Coveralls + # uses: coverallsapp/github-action@master + # with: + # github-token: ${{ secrets.GITHUB_TOKEN }} From 3416682bc3058f0c458b4020e142b93b921d31cd Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 12:44:14 +1200 Subject: [PATCH 06/15] Add ERC20 base token --- src/tokens/ERC20/ERC20Token.sol | 104 +++++++++++++++++++++++ src/tokens/ERC20/ERC20TokenFactory.sol | 37 +++++++++ src/tokens/ERC20/IERC20TokenFactory.sol | 23 ++++++ src/tokens/ERC721/ERC721Token.sol | 2 +- test/tokens/ERC20/ERC20Token.t.sol | 105 ++++++++++++++++++++++++ 5 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 src/tokens/ERC20/ERC20Token.sol create mode 100644 src/tokens/ERC20/ERC20TokenFactory.sol create mode 100644 src/tokens/ERC20/IERC20TokenFactory.sol create mode 100644 test/tokens/ERC20/ERC20Token.t.sol diff --git a/src/tokens/ERC20/ERC20Token.sol b/src/tokens/ERC20/ERC20Token.sol new file mode 100644 index 00000000..a287fffb --- /dev/null +++ b/src/tokens/ERC20/ERC20Token.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +error InvalidInitialization(); + +/** + * A ready made implementation of ERC-20. + */ +contract ERC20Token is ERC20, AccessControl { + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + + string private _name; + string private _symbol; + uint8 private _decimals; + + address private immutable _initializer; + bool private _initialized; + + /** + * Deploy contract. + */ + constructor() ERC20("", "") { + _initializer = msg.sender; + } + + /** + * Initialize contract. + * @param owner_ The owner of the contract + * @param name_ Name of the token + * @param symbol_ Symbol of the token + * @param decimals_ Number of decimals + * @dev This should be called immediately after deployment. + */ + function initialize(address owner_, string memory name_, string memory symbol_, uint8 decimals_) external { + if (msg.sender != _initializer || _initialized) { + revert InvalidInitialization(); + } + _initialized = true; + + _name = name_; + _symbol = symbol_; + _decimals = decimals_; + + _setupRole(DEFAULT_ADMIN_ROLE, owner_); + _setupRole(MINTER_ROLE, owner_); + } + + // + // Minting + // + + /** + * Mint tokens. + * @param _to Address to mint tokens to. + * @param _amount Amount of tokens to mint. + */ + function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) { + _mint(_to, _amount); + } + + // + // Views + // + + /** + * Check interface support. + * @param _interfaceId Interface id + * @return True if supported + */ + function supportsInterface(bytes4 _interfaceId) public view override returns (bool) { + return _interfaceId == type(IERC20).interfaceId || _interfaceId == type(IERC20Metadata).interfaceId + || AccessControl.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); + } + + // + // ERC20 Overrides + // + + /** + * Override the ERC20 name function. + */ + function name() public view override returns (string memory) { + return _name; + } + + /** + * Override the ERC20 symbol function. + */ + function symbol() public view override returns (string memory) { + return _symbol; + } + + /** + * Override the ERC20 decimals function. + */ + function decimals() public view override returns (uint8) { + return _decimals; + } +} diff --git a/src/tokens/ERC20/ERC20TokenFactory.sol b/src/tokens/ERC20/ERC20TokenFactory.sol new file mode 100644 index 00000000..cb36e847 --- /dev/null +++ b/src/tokens/ERC20/ERC20TokenFactory.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC20Token} from "./ERC20Token.sol"; +import {IERC20TokenFactory} from "./IERC20TokenFactory.sol"; +import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; + +contract ERC20TokenFactory is IERC20TokenFactory, ProxyDeployer { + address private immutable _implAddr; + + /** + * Creates an ERC-20 Token Factory. + */ + constructor() { + ERC20Token proxyImpl = new ERC20Token(); + _implAddr = address(proxyImpl); + } + + /** + * Creates an ERC-20 Token proxy. + * @param _owner The owner of the ERC-20 Token proxy + * @param _name The name of the ERC-20 Token proxy + * @param _symbol The symbol of the ERC-20 Token proxy + * @param _decimals The decimals of the ERC-20 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-20 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _symbol, uint8 _decimals, bytes32 _salt) + external + returns (address proxyAddr) + { + proxyAddr = _deployProxy(_implAddr, _salt); + ERC20Token(proxyAddr).initialize(_owner, _name, _symbol, _decimals); + emit ERC20TokenDeployed(proxyAddr); + return proxyAddr; + } +} diff --git a/src/tokens/ERC20/IERC20TokenFactory.sol b/src/tokens/ERC20/IERC20TokenFactory.sol new file mode 100644 index 00000000..6fc3ae8f --- /dev/null +++ b/src/tokens/ERC20/IERC20TokenFactory.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +interface IERC20TokenFactory { + /** + * Event emitted when a new ERC-20 Token proxy contract is deployed. + * @param proxyAddr The address of the deployed proxy. + */ + event ERC20TokenDeployed(address proxyAddr); + + /** + * Creates an ERC-20 Token proxy. + * @param _owner The owner of the ERC-20 Token proxy + * @param _name The name of the ERC-20 Token proxy + * @param _symbol The symbol of the ERC-20 Token proxy + * @param _decimals The decimals of the ERC-20 Token proxy + * @param _salt The deployment salt + * @return proxyAddr The address of the ERC-20 Token Proxy + */ + function deploy(address _owner, string memory _name, string memory _symbol, uint8 _decimals, bytes32 _salt) + external + returns (address proxyAddr); +} diff --git a/src/tokens/ERC721/ERC721Token.sol b/src/tokens/ERC721/ERC721Token.sol index 934637b7..0c42a4d0 100644 --- a/src/tokens/ERC721/ERC721Token.sol +++ b/src/tokens/ERC721/ERC721Token.sol @@ -146,7 +146,7 @@ contract ERC721Token is ERC721AQueryable, ERC2981, AccessControl { } /** - * Override the ERC721A name function. + * Override the ERC721A symbol function. */ function symbol() public view override (ERC721A, IERC721A) returns (string memory) { return _symbol; diff --git a/test/tokens/ERC20/ERC20Token.t.sol b/test/tokens/ERC20/ERC20Token.t.sol new file mode 100644 index 00000000..d43c6624 --- /dev/null +++ b/test/tokens/ERC20/ERC20Token.t.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import "forge-std/Test.sol"; +import {ERC20Token, InvalidInitialization} from "src/tokens/ERC20/ERC20Token.sol"; +import {ERC20TokenFactory} from "src/tokens/ERC20/ERC20TokenFactory.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +// Interfaces +import {IERC165} from "@0xsequence/erc-1155/contracts/interfaces/IERC165.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +contract ERC20TokenTest is Test { + // Redeclare events + event Transfer(address indexed from, address indexed to, uint256 value); + + ERC20Token private token; + + uint8 private constant DECIMALS = 18; + + address owner; + + function setUp() public { + owner = makeAddr("owner"); + + vm.deal(address(this), 100 ether); + vm.deal(owner, 100 ether); + + ERC20TokenFactory factory = new ERC20TokenFactory(); + token = ERC20Token(factory.deploy(owner, "name", "symbol", DECIMALS, 0x0)); + } + + function testReinitializeFails() public { + vm.expectRevert(InvalidInitialization.selector); + token.initialize(owner, "name", "symbol", DECIMALS); + } + + function testSupportsInterface() public { + assertTrue(token.supportsInterface(type(IERC165).interfaceId)); + assertTrue(token.supportsInterface(type(IERC20).interfaceId)); + assertTrue(token.supportsInterface(type(IERC20Metadata).interfaceId)); + } + + function testOwnerHasRoles() public { + assertTrue(token.hasRole(token.DEFAULT_ADMIN_ROLE(), owner)); + assertTrue(token.hasRole(token.MINTER_ROLE(), owner)); + } + + function testInitValues() public { + assertEq(token.name(), "name"); + assertEq(token.symbol(), "symbol"); + assertEq(token.decimals(), DECIMALS); + } + + // + // Minting + // + function testMintInvalidRole(address caller, uint256 amount) public { + vm.assume(caller != owner); + vm.assume(amount > 0); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(caller), + " is missing role ", + Strings.toHexString(uint256(token.MINTER_ROLE()), 32) + ) + ); + vm.prank(caller); + token.mint(caller, amount); + } + + function testMintOwner(uint256 amount) public { + vm.assume(amount > 0); + + vm.expectEmit(true, true, true, false, address(token)); + emit Transfer(address(0), owner, amount); + + vm.prank(owner); + token.mint(owner, amount); + + assertEq(token.balanceOf(owner), amount); + } + + function testMintWithRole(address minter, uint256 amount) public { + vm.assume(minter != owner); + vm.assume(minter != address(0)); + vm.assume(amount > 0); + // Give role + vm.startPrank(owner); + token.grantRole(token.MINTER_ROLE(), minter); + vm.stopPrank(); + + vm.expectEmit(true, true, true, false, address(token)); + emit Transfer(address(0), owner, amount); + + vm.prank(minter); + token.mint(owner, amount); + + assertEq(token.balanceOf(owner), amount); + } +} From 4250608888615aabeffb754bb7aeb50fd5cb3ae2 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 12:48:27 +1200 Subject: [PATCH 07/15] Update build scripts --- scripts/build.ts | 6 +++++- scripts/constants.ts | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/build.ts b/scripts/build.ts index a047eee9..ea610336 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -7,7 +7,11 @@ const exec = util.promisify(execNonPromise) const main = async () => { // Clean - await rmdir(BUILD_DIR, { recursive: true }) + try { + await rmdir(BUILD_DIR, { recursive: true }) + } catch (err) { + // Dir not found, ignore + } // Build with forge console.log('Building contracts') diff --git a/scripts/constants.ts b/scripts/constants.ts index 8f4826b3..f8bfe34b 100644 --- a/scripts/constants.ts +++ b/scripts/constants.ts @@ -1,5 +1,6 @@ export const BUILD_DIR = 'build' export const DEPLOYABLE_CONTRACT_NAMES = [ - 'ERC1155SaleFactory', - 'ERC721SaleFactory', + 'ERC20TokenFactory', + 'ERC721TokenFactory', + 'ERC1155TokenFactory', ] From 58672df473cc7f2d66a7dd4b687a77995ad9ccb3 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 12:57:07 +1200 Subject: [PATCH 08/15] Fix linting --- .github/workflows/ci.yaml | 9 +- .solhint.json | 8 + package.json | 6 +- src/proxies/ERC1967/Proxy.sol | 2 +- src/proxies/ERC1967/ProxyDeployer.sol | 2 +- .../ERC1155/Packed/ERC1155PackedToken.sol | 2 +- src/utils/StorageSlot.sol | 8 +- yarn.lock | 395 +++++++++++++++++- 8 files changed, 415 insertions(+), 17 deletions(-) create mode 100644 .solhint.json diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c3f7000b..3d021f01 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,7 +42,14 @@ jobs: node_modules */*/node_modules key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json', '**/yarn.lock') }} - - run: yarn lint:sol + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Run linting + run: yarn lint:sol foundry-tests: name: Foundry tests diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 00000000..99e21211 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,8 @@ +{ + "extends": ["solhint:recommended"], + "rules": { + "compiler-version": ["error", "^0.8.17"], + "func-visibility": ["warn", { "ignoreConstructors": true }], + "reason-string": ["warn", { "maxLength": 96 }] + } +} diff --git a/package.json b/package.json index 8506b7de..cc3612da 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "build": "ts-node scripts/build.ts", "test": "forge test", "lint:init": "husky install", - "lint:sol": "forge fmt" + "lint:sol": "solhint \"./src/**/*.sol\" \"./tests/**/*.sol\"", + "format:sol": "forge fmt" }, "files": [ "src", @@ -30,12 +31,13 @@ "erc721a-upgradeable": "^4.2.3" }, "lint-staged": { - "**/*.sol": "yarn lint:sol" + "**/*.sol": "yarn lint:sol && yarn format:sol" }, "devDependencies": { "@types/node": "^20.1.0", "husky": "^8.0.3", "lint-staged": "^13.2.2", + "solhint": "^3.4.1", "ts-node": "^10.9.1", "typescript": "^5.0.4" } diff --git a/src/proxies/ERC1967/Proxy.sol b/src/proxies/ERC1967/Proxy.sol index 833e49ef..a2da3ee2 100644 --- a/src/proxies/ERC1967/Proxy.sol +++ b/src/proxies/ERC1967/Proxy.sol @@ -34,7 +34,7 @@ contract Proxy is IERC1967 { */ function proxy() private { address target = _getImplementation(); - assembly { + assembly { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), target, ptr, calldatasize(), 0, 0) diff --git a/src/proxies/ERC1967/ProxyDeployer.sol b/src/proxies/ERC1967/ProxyDeployer.sol index a61f8a63..a1e9e0b3 100644 --- a/src/proxies/ERC1967/ProxyDeployer.sol +++ b/src/proxies/ERC1967/ProxyDeployer.sol @@ -15,7 +15,7 @@ abstract contract ProxyDeployer is ProxyDeployerErrors { bytes memory code = _getProxyCode(implAddr); // Deploy it - assembly { + assembly { // solhint-disable-line no-inline-assembly proxyAddr := create2(0, add(code, 32), mload(code), salt) } if (proxyAddr == address(0)) { diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol index 1a41db1b..0bfde317 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -32,7 +32,7 @@ contract ERC1155PackedToken is /** * Initialize contract. */ - constructor() ERC1155Metadata("", "") {} + constructor() ERC1155Metadata("", "") {} // solhint-disable-line no-empty-blocks /** * Initialize the contract. diff --git a/src/utils/StorageSlot.sol b/src/utils/StorageSlot.sol index 775a4b6b..d0c0ef3a 100644 --- a/src/utils/StorageSlot.sol +++ b/src/utils/StorageSlot.sol @@ -30,7 +30,7 @@ library StorageSlot { * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { - assembly { + assembly { // solhint-disable-line no-inline-assembly r.slot := slot } } @@ -39,7 +39,7 @@ library StorageSlot { * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { - assembly { + assembly { // solhint-disable-line no-inline-assembly r.slot := slot } } @@ -48,7 +48,7 @@ library StorageSlot { * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { - assembly { + assembly { // solhint-disable-line no-inline-assembly r.slot := slot } } @@ -57,7 +57,7 @@ library StorageSlot { * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { - assembly { + assembly { // solhint-disable-line no-inline-assembly r.slot := slot } } diff --git a/yarn.lock b/yarn.lock index 94dc5bf6..aaa018cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11,11 +11,7 @@ "@ethersproject/providers" "^5.7.2" ethers "^5.7.2" -<<<<<<< HEAD -"@0xsequence/erc-1155@^4.0.2": -======= "@0xsequence/erc-1155@^4.0.3": ->>>>>>> e4c96a7 (Base implementations) version "4.0.3" resolved "https://registry.yarnpkg.com/@0xsequence/erc-1155/-/erc-1155-4.0.3.tgz#b9b890c1ced04a84f36be22dd20424b43b9e1da2" integrity sha512-vDh4OEuq0bR3iIqhsxpuRpczH5GxwH/mjBWm9uP6VYKnKM36ZBLApSNUlIOCXYRCS0DYFxsdvYjAemb3w1l4ow== @@ -31,6 +27,27 @@ dependencies: "@0xsequence/erc-1155" "^4.0.1" +"@babel/code-frame@^7.0.0": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -403,6 +420,13 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== +"@solidity-parser/parser@^0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.0.tgz#1fb418c816ca1fc3a1e94b08bcfe623ec4e1add4" + integrity sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q== + dependencies: + antlr4ts "^0.5.0-alpha.4" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -451,6 +475,26 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv@^6.12.6: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -468,7 +512,14 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== -ansi-styles@^4.0.0: +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -480,16 +531,41 @@ ansi-styles@^6.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +antlr4@^4.11.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.0.tgz#25c0b17f0d9216de114303d38bafd6f181d5447f" + integrity sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +ast-parents@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + bech32@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -505,6 +581,13 @@ bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -517,11 +600,33 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + chalk@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -550,6 +655,13 @@ cli-truncate@^3.1.0: slice-ansi "^5.0.0" string-width "^5.0.0" +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -557,6 +669,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -572,6 +689,16 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +cosmiconfig@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" + integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -636,6 +763,18 @@ erc721a@^4.2.3: resolved "https://registry.yarnpkg.com/erc721a/-/erc721a-4.2.3.tgz#ca6469b0e54afb0f614272c2147dc4cb49ff223f" integrity sha512-0deF0hOOK1XI1Vxv3NKDh2E9sgzRlENuOoexjXRJIRfYCsLlqi9ejl2RF6Wcd9HfH0ldqC03wleQ2WDjxoOUvA== +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" @@ -687,6 +826,21 @@ execa@^7.0.0: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -694,11 +848,37 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -726,16 +906,42 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +ignore@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -inherits@^2.0.3, inherits@^2.0.4: +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -766,11 +972,43 @@ js-sha3@0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + lilconfig@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + lint-staged@^13.2.2: version "13.2.2" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" @@ -804,6 +1042,16 @@ listr2@^5.0.7: through "^2.3.8" wrap-ansi "^7.0.0" +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -852,6 +1100,13 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -874,6 +1129,13 @@ object-inspect@^1.12.3: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -895,6 +1157,23 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -905,6 +1184,11 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -915,6 +1199,31 @@ pidtree@^0.6.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +prettier@^2.8.3: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -940,6 +1249,11 @@ scrypt-js@3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -983,12 +1297,37 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" +solhint@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46" + integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg== + dependencies: + "@solidity-parser/parser" "^0.16.0" + ajv "^6.12.6" + antlr4 "^4.11.0" + ast-parents "^0.0.1" + chalk "^4.1.2" + commander "^10.0.0" + cosmiconfig "^8.0.0" + fast-diff "^1.2.0" + glob "^8.0.3" + ignore "^5.2.4" + js-yaml "^4.1.0" + lodash "^4.17.21" + pluralize "^8.0.0" + semver "^6.3.0" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" + optionalDependencies: + prettier "^2.8.3" + string-argv@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -1025,6 +1364,36 @@ strip-final-newline@^3.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +table@^6.8.1: + 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" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1071,6 +1440,13 @@ typescript@^5.0.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -1101,6 +1477,11 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" From e3e6139d5a15621b9e6ed1f305ed627e0c6793c1 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 14:01:23 +1200 Subject: [PATCH 09/15] Hash salt with sender for security --- src/tokens/ERC1155/ERC1155TokenFactory.sol | 3 ++- src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol | 3 ++- src/tokens/ERC20/ERC20TokenFactory.sol | 3 ++- src/tokens/ERC721/ERC721TokenFactory.sol | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tokens/ERC1155/ERC1155TokenFactory.sol b/src/tokens/ERC1155/ERC1155TokenFactory.sol index 850f559c..d597f80d 100644 --- a/src/tokens/ERC1155/ERC1155TokenFactory.sol +++ b/src/tokens/ERC1155/ERC1155TokenFactory.sol @@ -23,12 +23,13 @@ contract ERC1155TokenFactory is IERC1155TokenFactory, ProxyDeployer { * @param _baseURI The base URI of the ERC-1155 Token proxy * @param _salt The deployment salt * @return proxyAddr The address of the ERC-1155 Token Proxy + * @dev The provided `_salt` is hashed with the caller address for security. */ function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, _salt); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); ERC1155Token(proxyAddr).initialize(_owner, _name, _baseURI); emit ERC1155TokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol index f10dd9ca..f0a92ae4 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol @@ -23,12 +23,13 @@ contract ERC1155PackedTokenFactory is IERC1155PackedTokenFactory, ProxyDeployer * @param _baseURI The base URI of the ERC-1155 Packed Token proxy * @param _salt The deployment salt * @return proxyAddr The address of the ERC-1155 Packed Token Proxy + * @dev The provided `_salt` is hashed with the caller address for security. */ function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, _salt); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); ERC1155PackedToken(proxyAddr).initialize(_owner, _name, _baseURI); emit ERC1155PackedTokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC20/ERC20TokenFactory.sol b/src/tokens/ERC20/ERC20TokenFactory.sol index cb36e847..17d6eced 100644 --- a/src/tokens/ERC20/ERC20TokenFactory.sol +++ b/src/tokens/ERC20/ERC20TokenFactory.sol @@ -24,12 +24,13 @@ contract ERC20TokenFactory is IERC20TokenFactory, ProxyDeployer { * @param _decimals The decimals of the ERC-20 Token proxy * @param _salt The deployment salt * @return proxyAddr The address of the ERC-20 Token Proxy + * @dev The provided `_salt` is hashed with the caller address for security. */ function deploy(address _owner, string memory _name, string memory _symbol, uint8 _decimals, bytes32 _salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, _salt); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); ERC20Token(proxyAddr).initialize(_owner, _name, _symbol, _decimals); emit ERC20TokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC721/ERC721TokenFactory.sol b/src/tokens/ERC721/ERC721TokenFactory.sol index ff20e99a..f11972fa 100644 --- a/src/tokens/ERC721/ERC721TokenFactory.sol +++ b/src/tokens/ERC721/ERC721TokenFactory.sol @@ -24,12 +24,13 @@ contract ERC721TokenFactory is IERC721TokenFactory, ProxyDeployer { * @param _baseURI The base URI of the ERC-721 Token proxy * @param _salt The deployment salt * @return proxyAddr The address of the ERC-721 Token Proxy + * @dev The provided `_salt` is hashed with the caller address for security. */ function deploy(address _owner, string memory _name, string memory _symbol, string memory _baseURI, bytes32 _salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, _salt); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); ERC721Token(proxyAddr).initialize(_owner, _name, _symbol, _baseURI); emit ERC721TokenDeployed(proxyAddr); return proxyAddr; From 2abb41484791369d79fdd9d207742d53c43aa77f Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 14:07:47 +1200 Subject: [PATCH 10/15] Abstract ERC2981 control --- src/tokens/ERC1155/ERC1155Token.sol | 37 ++--------- .../ERC1155/Packed/ERC1155PackedToken.sol | 39 ++---------- src/tokens/ERC721/ERC721Token.sol | 39 ++---------- src/tokens/common/ERC2981Controlled.sol | 62 +++++++++++++++++++ 4 files changed, 75 insertions(+), 102 deletions(-) create mode 100644 src/tokens/common/ERC2981Controlled.sol diff --git a/src/tokens/ERC1155/ERC1155Token.sol b/src/tokens/ERC1155/ERC1155Token.sol index f81ed5c5..4a7f1783 100644 --- a/src/tokens/ERC1155/ERC1155Token.sol +++ b/src/tokens/ERC1155/ERC1155Token.sol @@ -4,18 +4,16 @@ pragma solidity ^0.8.17; import {ERC1155, ERC1155MintBurn} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155MintBurn.sol"; import {ERC1155Meta} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Meta.sol"; import {ERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; -import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; -import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {ERC2981Controlled} from "../common/ERC2981Controlled.sol"; error InvalidInitialization(); /** * A ready made implementation of ERC-1155. */ -contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981, AccessControl { +contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981Controlled { bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); address private immutable _initializer; bool private _initialized; @@ -78,33 +76,6 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981, _batchMint(_to, _tokenIds, _amounts, _data); } - // - // Royalty - // - - /** - * Sets the royalty information that all ids in this contract will default to. - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - */ - function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { - _setDefaultRoyalty(_receiver, _feeNumerator); - } - - /** - * Sets the royalty information that a given token id in this contract will use. - * @param _tokenId The token id to set the royalty information for - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - * @notice This overrides the default royalty information for this token id - */ - function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) - external - onlyRole(ROYALTY_ADMIN_ROLE) - { - _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); - } - // // Metadata // @@ -137,11 +108,11 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981, function supportsInterface(bytes4 _interfaceId) public view - override (ERC1155, ERC1155Metadata, ERC2981, AccessControl) + override (ERC1155, ERC1155Metadata, ERC2981Controlled) returns (bool) { return ERC1155.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) - || ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) + || ERC2981Controlled.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); } } diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol index 0bfde317..6d0dc703 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -8,8 +8,7 @@ import { import {ERC1155MetaPackedBalance} from "@0xsequence/erc-1155/contracts/tokens/ERC1155PackedBalance/ERC1155MetaPackedBalance.sol"; import {ERC1155Metadata} from "@0xsequence/erc-1155/contracts/tokens/ERC1155/ERC1155Metadata.sol"; -import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; -import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {ERC2981Controlled} from "../../common/ERC2981Controlled.sol"; error InvalidInitialization(); @@ -19,13 +18,10 @@ error InvalidInitialization(); contract ERC1155PackedToken is ERC1155MintBurnPackedBalance, ERC1155MetaPackedBalance, - ERC1155Metadata, - ERC2981, - AccessControl + ERC1155Metadata,ERC2981Controlled { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); - bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); bool private _initialized; @@ -84,33 +80,6 @@ contract ERC1155PackedToken is _batchMint(_to, _tokenIds, _amounts, _data); } - // - // Royalty - // - - /** - * Sets the royalty information that all ids in this contract will default to. - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - */ - function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { - _setDefaultRoyalty(_receiver, _feeNumerator); - } - - /** - * Sets the royalty information that a given token id in this contract will use. - * @param _tokenId The token id to set the royalty information for - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - * @notice This overrides the default royalty information for this token id - */ - function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) - external - onlyRole(ROYALTY_ADMIN_ROLE) - { - _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); - } - // // Metadata // @@ -143,11 +112,11 @@ contract ERC1155PackedToken is function supportsInterface(bytes4 _interfaceId) public view - override (ERC1155PackedBalance, ERC1155Metadata, ERC2981, AccessControl) + override (ERC1155PackedBalance, ERC1155Metadata, ERC2981Controlled) returns (bool) { return ERC1155PackedBalance.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) - || ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) + || ERC2981Controlled.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); } } diff --git a/src/tokens/ERC721/ERC721Token.sol b/src/tokens/ERC721/ERC721Token.sol index 0c42a4d0..b9e310f8 100644 --- a/src/tokens/ERC721/ERC721Token.sol +++ b/src/tokens/ERC721/ERC721Token.sol @@ -4,18 +4,16 @@ pragma solidity ^0.8.17; import { ERC721AQueryable, IERC721AQueryable, ERC721A, IERC721A } from "erc721a/contracts/extensions/ERC721AQueryable.sol"; -import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; -import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {ERC2981Controlled} from "../common/ERC2981Controlled.sol"; error InvalidInitialization(); /** * A ready made implementation of ERC-721. */ -contract ERC721Token is ERC721AQueryable, ERC2981, AccessControl { +contract ERC721Token is ERC721AQueryable, ERC2981Controlled { bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); string private baseURI; // Missing _ due to _baseURI() function in ERC721A string private _name; @@ -68,33 +66,6 @@ contract ERC721Token is ERC721AQueryable, ERC2981, AccessControl { _mint(_to, _amount); } - // - // Royalty - // - - /** - * Sets the royalty information that all ids in this contract will default to. - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - */ - function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { - _setDefaultRoyalty(_receiver, _feeNumerator); - } - - /** - * Sets the royalty information that a given token id in this contract will use. - * @param _tokenId The token id to set the royalty information for - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) - * @notice This overrides the default royalty information for this token id - */ - function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) - external - onlyRole(ROYALTY_ADMIN_ROLE) - { - _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); - } - // // Metadata // @@ -119,12 +90,12 @@ contract ERC721Token is ERC721AQueryable, ERC2981, AccessControl { function supportsInterface(bytes4 _interfaceId) public view - override (ERC721A, IERC721A, ERC2981, AccessControl) + override (ERC721A, IERC721A, ERC2981Controlled) returns (bool) { return _interfaceId == type(IERC721A).interfaceId || _interfaceId == type(IERC721AQueryable).interfaceId - || ERC721A.supportsInterface(_interfaceId) || ERC2981.supportsInterface(_interfaceId) - || AccessControl.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); + || ERC721A.supportsInterface(_interfaceId) || ERC2981Controlled.supportsInterface(_interfaceId) + || super.supportsInterface(_interfaceId); } // diff --git a/src/tokens/common/ERC2981Controlled.sol b/src/tokens/common/ERC2981Controlled.sol new file mode 100644 index 00000000..17f7854a --- /dev/null +++ b/src/tokens/common/ERC2981Controlled.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +/** + * An implementation of ERC-2981 that allows updates by roles. + */ +abstract contract ERC2981Controlled is + ERC2981, + AccessControl +{ + bytes32 public constant ROYALTY_ADMIN_ROLE = keccak256("ROYALTY_ADMIN_ROLE"); + + // + // Royalty + // + + /** + * Sets the royalty information that all ids in this contract will default to. + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + */ + function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { + _setDefaultRoyalty(_receiver, _feeNumerator); + } + + /** + * Sets the royalty information that a given token id in this contract will use. + * @param _tokenId The token id to set the royalty information for + * @param _receiver Address of who should be sent the royalty payment + * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @notice This overrides the default royalty information for this token id + */ + function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) + external + onlyRole(ROYALTY_ADMIN_ROLE) + { + _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); + } + + // + // Views + // + + /** + * Check interface support. + * @param _interfaceId Interface id + * @return True if supported + */ + function supportsInterface(bytes4 _interfaceId) + public + view + virtual + override (ERC2981, AccessControl) + returns (bool) + { + return ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) + || super.supportsInterface(_interfaceId); + } +} From 304f1c53f96ab4431d0a59ee68dd02219cfada0b Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 7 Jun 2023 14:08:53 +1200 Subject: [PATCH 11/15] Keep init rules consistent --- src/tokens/ERC1155/Packed/ERC1155PackedToken.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol index 6d0dc703..f51c7d6a 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -23,12 +23,15 @@ contract ERC1155PackedToken is bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); + address private immutable _initializer; bool private _initialized; /** * Initialize contract. */ - constructor() ERC1155Metadata("", "") {} // solhint-disable-line no-empty-blocks + constructor() ERC1155Metadata("", "") { + _initializer = msg.sender; + } /** * Initialize the contract. @@ -38,10 +41,11 @@ contract ERC1155PackedToken is * @dev This should be called immediately after deployment. */ function initialize(address _owner, string memory _name, string memory _baseURI) public { - if (_initialized) { + if (msg.sender != _initializer || _initialized) { revert InvalidInitialization(); } _initialized = true; + name = _name; baseURI = _baseURI; From 2bc9bfdb251e8315877195555fad055a1932cb8d Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Thu, 8 Jun 2023 13:58:03 +1200 Subject: [PATCH 12/15] Variable naming convention update --- src/proxies/ERC1967/Proxy.sol | 14 ++-- src/proxies/ERC1967/ProxyDeployer.sol | 4 +- src/tokens/ERC1155/ERC1155Token.sol | 76 +++++++++---------- src/tokens/ERC1155/ERC1155TokenFactory.sol | 20 ++--- src/tokens/ERC1155/IERC1155TokenFactory.sol | 10 +-- .../ERC1155/Packed/ERC1155PackedToken.sol | 76 +++++++++---------- .../Packed/ERC1155PackedTokenFactory.sol | 20 ++--- .../Packed/IERC1155PackedTokenFactory.sol | 10 +-- src/tokens/ERC20/ERC20Token.sol | 58 +++++++------- src/tokens/ERC20/ERC20TokenFactory.sol | 22 +++--- src/tokens/ERC20/IERC20TokenFactory.sol | 12 +-- src/tokens/ERC721/ERC721Token.sol | 64 ++++++++-------- src/tokens/ERC721/ERC721TokenFactory.sol | 22 +++--- src/tokens/ERC721/IERC721TokenFactory.sol | 12 +-- src/tokens/common/ERC2981Controlled.sol | 26 +++---- 15 files changed, 223 insertions(+), 223 deletions(-) diff --git a/src/proxies/ERC1967/Proxy.sol b/src/proxies/ERC1967/Proxy.sol index a2da3ee2..1cb44d61 100644 --- a/src/proxies/ERC1967/Proxy.sol +++ b/src/proxies/ERC1967/Proxy.sol @@ -5,14 +5,14 @@ import {IERC1967} from "./IERC1967.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; contract Proxy is IERC1967 { - bytes32 internal constant _IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); + bytes32 internal constant IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); /** * Initializes the contract, setting proxy implementation address. */ - constructor(address _implementation) { - _setImplementation(_implementation); - emit Upgraded(_implementation); + constructor(address implementation) { + _setImplementation(implementation); + emit Upgraded(implementation); } /** @@ -49,14 +49,14 @@ contract Proxy is IERC1967 { /** * Set the implementation address. */ - function _setImplementation(address _implementation) internal { - StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = _implementation; + function _setImplementation(address implementation) internal { + StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = implementation; } /** * Returns the address of the current implementation. */ function _getImplementation() internal view returns (address) { - return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } } diff --git a/src/proxies/ERC1967/ProxyDeployer.sol b/src/proxies/ERC1967/ProxyDeployer.sol index a1e9e0b3..e590c4f7 100644 --- a/src/proxies/ERC1967/ProxyDeployer.sol +++ b/src/proxies/ERC1967/ProxyDeployer.sol @@ -43,8 +43,8 @@ abstract contract ProxyDeployer is ProxyDeployerErrors { */ function _predictProxyAddress(bytes memory code, bytes32 salt) private view returns (address proxyAddr) { address deployer = address(this); - bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(code))); - return address(uint160(uint256(_data))); + bytes32 data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(code))); + return address(uint160(uint256(data))); } /** diff --git a/src/tokens/ERC1155/ERC1155Token.sol b/src/tokens/ERC1155/ERC1155Token.sol index 4a7f1783..c27e085d 100644 --- a/src/tokens/ERC1155/ERC1155Token.sol +++ b/src/tokens/ERC1155/ERC1155Token.sol @@ -15,36 +15,36 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - address private immutable _initializer; - bool private _initialized; + address private immutable initializer; + bool private initialized; /** * Initialize contract. */ constructor() ERC1155Metadata("", "") { - _initializer = msg.sender; + initializer = msg.sender; } /** * Initialize the contract. - * @param _owner Owner address. - * @param _name Token name. - * @param _baseURI Base URI for token metadata. + * @param owner Owner address. + * @param name_ Token name. + * @param baseURI_ Base URI for token metadata. * @dev This should be called immediately after deployment. */ - function initialize(address _owner, string memory _name, string memory _baseURI) public { - if (msg.sender != _initializer || _initialized) { + function initialize(address owner, string memory name_, string memory baseURI_) public { + if (msg.sender != initializer || initialized) { revert InvalidInitialization(); } - _initialized = true; + initialized = true; - name = _name; - baseURI = _baseURI; + name = name_; + baseURI = baseURI_; - _setupRole(DEFAULT_ADMIN_ROLE, _owner); - _setupRole(MINTER_ROLE, _owner); - _setupRole(ROYALTY_ADMIN_ROLE, _owner); - _setupRole(METADATA_ADMIN_ROLE, _owner); + _setupRole(DEFAULT_ADMIN_ROLE, owner); + _setupRole(MINTER_ROLE, owner); + _setupRole(ROYALTY_ADMIN_ROLE, owner); + _setupRole(METADATA_ADMIN_ROLE, owner); } // @@ -53,27 +53,27 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _tokenId Token ID to mint. - * @param _amount Amount of tokens to mint. - * @param _data Data to pass if receiver is contract. + * @param to Address to mint tokens to. + * @param tokenId Token ID to mint. + * @param amount Amount of tokens to mint. + * @param data Data to pass if receiver is contract. */ - function mint(address _to, uint256 _tokenId, uint256 _amount, bytes memory _data) external onlyRole(MINTER_ROLE) { - _mint(_to, _tokenId, _amount, _data); + function mint(address to, uint256 tokenId, uint256 amount, bytes memory data) external onlyRole(MINTER_ROLE) { + _mint(to, tokenId, amount, data); } /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _tokenIds Token IDs to mint. - * @param _amounts Amounts of tokens to mint. - * @param _data Data to pass if receiver is contract. + * @param to Address to mint tokens to. + * @param tokenIds Token IDs to mint. + * @param amounts Amounts of tokens to mint. + * @param data Data to pass if receiver is contract. */ - function batchMint(address _to, uint256[] memory _tokenIds, uint256[] memory _amounts, bytes memory _data) + function batchMint(address to, uint256[] memory tokenIds, uint256[] memory amounts, bytes memory data) external onlyRole(MINTER_ROLE) { - _batchMint(_to, _tokenIds, _amounts, _data); + _batchMint(to, tokenIds, amounts, data); } // @@ -82,18 +82,18 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C /** * Update the base URL of token's URI. - * @param _baseMetadataURI New base URL of token's URI + * @param baseURI_ New base URL of token's URI */ - function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { - _setBaseMetadataURI(_baseMetadataURI); + function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(baseURI_); } /** * Update the name of the contract. - * @param _name New contract name + * @param name_ New contract name */ - function setContractName(string memory _name) external onlyRole(METADATA_ADMIN_ROLE) { - _setContractName(_name); + function setContractName(string memory name_) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(name_); } // @@ -102,17 +102,17 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C /** * Check interface support. - * @param _interfaceId Interface id + * @param interfaceId Interface id * @return True if supported */ - function supportsInterface(bytes4 _interfaceId) + function supportsInterface(bytes4 interfaceId) public view override (ERC1155, ERC1155Metadata, ERC2981Controlled) returns (bool) { - return ERC1155.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) - || ERC2981Controlled.supportsInterface(_interfaceId) - || super.supportsInterface(_interfaceId); + return ERC1155.supportsInterface(interfaceId) || ERC1155Metadata.supportsInterface(interfaceId) + || ERC2981Controlled.supportsInterface(interfaceId) + || super.supportsInterface(interfaceId); } } diff --git a/src/tokens/ERC1155/ERC1155TokenFactory.sol b/src/tokens/ERC1155/ERC1155TokenFactory.sol index d597f80d..3c54a808 100644 --- a/src/tokens/ERC1155/ERC1155TokenFactory.sol +++ b/src/tokens/ERC1155/ERC1155TokenFactory.sol @@ -6,31 +6,31 @@ import {IERC1155TokenFactory} from "./IERC1155TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC1155TokenFactory is IERC1155TokenFactory, ProxyDeployer { - address private immutable _implAddr; + address private immutable implAddr; /** * Creates an ERC-1155 Token Factory. */ constructor() { ERC1155Token proxyImpl = new ERC1155Token(); - _implAddr = address(proxyImpl); + implAddr = address(proxyImpl); } /** * Creates an ERC-1155 Token proxy. - * @param _owner The owner of the ERC-1155 Token proxy - * @param _name The name of the ERC-1155 Token proxy - * @param _baseURI The base URI of the ERC-1155 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-1155 Token proxy + * @param name The name of the ERC-1155 Token proxy + * @param baseURI The base URI of the ERC-1155 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-1155 Token Proxy - * @dev The provided `_salt` is hashed with the caller address for security. + * @dev The provided `salt` is hashed with the caller address for security. */ - function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory baseURI, bytes32 salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); - ERC1155Token(proxyAddr).initialize(_owner, _name, _baseURI); + proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + ERC1155Token(proxyAddr).initialize(owner, name, baseURI); emit ERC1155TokenDeployed(proxyAddr); return proxyAddr; } diff --git a/src/tokens/ERC1155/IERC1155TokenFactory.sol b/src/tokens/ERC1155/IERC1155TokenFactory.sol index 23b79a0a..a266742f 100644 --- a/src/tokens/ERC1155/IERC1155TokenFactory.sol +++ b/src/tokens/ERC1155/IERC1155TokenFactory.sol @@ -10,13 +10,13 @@ interface IERC1155TokenFactory { /** * Creates an ERC-1155 Token proxy. - * @param _owner The owner of the ERC-1155 Token proxy - * @param _name The name of the ERC-1155 Token proxy - * @param _baseURI The base URI of the ERC-1155 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-1155 Token proxy + * @param name The name of the ERC-1155 Token proxy + * @param baseURI The base URI of the ERC-1155 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-1155 Token Proxy */ - function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory baseURI, bytes32 salt) external returns (address proxyAddr); } diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol index f51c7d6a..71b91d3a 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -23,36 +23,36 @@ contract ERC1155PackedToken is bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); - address private immutable _initializer; - bool private _initialized; + address private immutable initializer; + bool private initialized; /** * Initialize contract. */ constructor() ERC1155Metadata("", "") { - _initializer = msg.sender; + initializer = msg.sender; } /** * Initialize the contract. - * @param _owner Owner address. - * @param _name Token name. - * @param _baseURI Base URI for token metadata. + * @param owner Owner address. + * @param name_ Token name. + * @param baseURI_ Base URI for token metadata. * @dev This should be called immediately after deployment. */ - function initialize(address _owner, string memory _name, string memory _baseURI) public { - if (msg.sender != _initializer || _initialized) { + function initialize(address owner, string memory name_, string memory baseURI_) public { + if (msg.sender != initializer || initialized) { revert InvalidInitialization(); } - _initialized = true; + initialized = true; - name = _name; - baseURI = _baseURI; + name = name_; + baseURI = baseURI_; - _setupRole(DEFAULT_ADMIN_ROLE, _owner); - _setupRole(MINTER_ROLE, _owner); - _setupRole(ROYALTY_ADMIN_ROLE, _owner); - _setupRole(METADATA_ADMIN_ROLE, _owner); + _setupRole(DEFAULT_ADMIN_ROLE, owner); + _setupRole(MINTER_ROLE, owner); + _setupRole(ROYALTY_ADMIN_ROLE, owner); + _setupRole(METADATA_ADMIN_ROLE, owner); } // @@ -61,27 +61,27 @@ contract ERC1155PackedToken is /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _tokenId Token ID to mint. - * @param _amount Amount of tokens to mint. - * @param _data Data to pass if receiver is contract. + * @param to Address to mint tokens to. + * @param tokenId Token ID to mint. + * @param amount Amount of tokens to mint. + * @param data Data to pass if receiver is contract. */ - function mint(address _to, uint256 _tokenId, uint256 _amount, bytes memory _data) external onlyRole(MINTER_ROLE) { - _mint(_to, _tokenId, _amount, _data); + function mint(address to, uint256 tokenId, uint256 amount, bytes memory data) external onlyRole(MINTER_ROLE) { + _mint(to, tokenId, amount, data); } /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _tokenIds Token IDs to mint. - * @param _amounts Amounts of tokens to mint. - * @param _data Data to pass if receiver is contract. + * @param to Address to mint tokens to. + * @param tokenIds Token IDs to mint. + * @param amounts Amounts of tokens to mint. + * @param data Data to pass if receiver is contract. */ - function batchMint(address _to, uint256[] memory _tokenIds, uint256[] memory _amounts, bytes memory _data) + function batchMint(address to, uint256[] memory tokenIds, uint256[] memory amounts, bytes memory data) external onlyRole(MINTER_ROLE) { - _batchMint(_to, _tokenIds, _amounts, _data); + _batchMint(to, tokenIds, amounts, data); } // @@ -90,18 +90,18 @@ contract ERC1155PackedToken is /** * Update the base URL of token's URI. - * @param _baseMetadataURI New base URL of token's URI + * @param baseURI_ New base URL of token's URI */ - function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { - _setBaseMetadataURI(_baseMetadataURI); + function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(baseURI_); } /** * Update the name of the contract. - * @param _name New contract name + * @param name_ New contract name */ - function setContractName(string memory _name) external onlyRole(METADATA_ADMIN_ROLE) { - _setContractName(_name); + function setContractName(string memory name_) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(name_); } // @@ -110,17 +110,17 @@ contract ERC1155PackedToken is /** * Check interface support. - * @param _interfaceId Interface id + * @param interfaceId Interface id * @return True if supported */ - function supportsInterface(bytes4 _interfaceId) + function supportsInterface(bytes4 interfaceId) public view override (ERC1155PackedBalance, ERC1155Metadata, ERC2981Controlled) returns (bool) { - return ERC1155PackedBalance.supportsInterface(_interfaceId) || ERC1155Metadata.supportsInterface(_interfaceId) - || ERC2981Controlled.supportsInterface(_interfaceId) - || super.supportsInterface(_interfaceId); + return ERC1155PackedBalance.supportsInterface(interfaceId) || ERC1155Metadata.supportsInterface(interfaceId) + || ERC2981Controlled.supportsInterface(interfaceId) + || super.supportsInterface(interfaceId); } } diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol index f0a92ae4..9f483f7b 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol @@ -6,31 +6,31 @@ import {IERC1155PackedTokenFactory} from "./IERC1155PackedTokenFactory.sol"; import {ProxyDeployer} from "../../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC1155PackedTokenFactory is IERC1155PackedTokenFactory, ProxyDeployer { - address private immutable _implAddr; + address private immutable implAddr; /** * Creates an ERC-1155 Token Factory. */ constructor() { ERC1155PackedToken proxyImpl = new ERC1155PackedToken(); - _implAddr = address(proxyImpl); + implAddr = address(proxyImpl); } /** * Creates an ERC-1155 Packed Token proxy. - * @param _owner The owner of the ERC-1155 Packed Token proxy - * @param _name The name of the ERC-1155 Packed Token proxy - * @param _baseURI The base URI of the ERC-1155 Packed Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-1155 Packed Token proxy + * @param name The name of the ERC-1155 Packed Token proxy + * @param baseURI The base URI of the ERC-1155 Packed Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-1155 Packed Token Proxy - * @dev The provided `_salt` is hashed with the caller address for security. + * @dev The provided `salt` is hashed with the caller address for security. */ - function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory baseURI, bytes32 salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); - ERC1155PackedToken(proxyAddr).initialize(_owner, _name, _baseURI); + proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + ERC1155PackedToken(proxyAddr).initialize(owner, name, baseURI); emit ERC1155PackedTokenDeployed(proxyAddr); return proxyAddr; } diff --git a/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol index e4f7ef12..27ab1339 100644 --- a/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol +++ b/src/tokens/ERC1155/Packed/IERC1155PackedTokenFactory.sol @@ -10,13 +10,13 @@ interface IERC1155PackedTokenFactory { /** * Creates an ERC-1155 Packed Token proxy. - * @param _owner The owner of the ERC-1155 Packed Token proxy - * @param _name The name of the ERC-1155 Packed Token proxy - * @param _baseURI The base URI of the ERC-1155 Packed Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-1155 Packed Token proxy + * @param name The name of the ERC-1155 Packed Token proxy + * @param baseURI The base URI of the ERC-1155 Packed Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-1155 Packed Token Proxy */ - function deploy(address _owner, string memory _name, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory baseURI, bytes32 salt) external returns (address proxyAddr); } diff --git a/src/tokens/ERC20/ERC20Token.sol b/src/tokens/ERC20/ERC20Token.sol index a287fffb..308579f3 100644 --- a/src/tokens/ERC20/ERC20Token.sol +++ b/src/tokens/ERC20/ERC20Token.sol @@ -14,40 +14,40 @@ error InvalidInitialization(); contract ERC20Token is ERC20, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - string private _name; - string private _symbol; - uint8 private _decimals; + string private tokenName; + string private tokenSymbol; + uint8 private tokenDecimals; - address private immutable _initializer; - bool private _initialized; + address private immutable initializer; + bool private initialized; /** * Deploy contract. */ constructor() ERC20("", "") { - _initializer = msg.sender; + initializer = msg.sender; } /** * Initialize contract. - * @param owner_ The owner of the contract - * @param name_ Name of the token - * @param symbol_ Symbol of the token - * @param decimals_ Number of decimals + * @param owner The owner of the contract + * @param tokenName_ Name of the token + * @param tokenSymbol_ Symbol of the token + * @param tokenDecimals_ Number of decimals * @dev This should be called immediately after deployment. */ - function initialize(address owner_, string memory name_, string memory symbol_, uint8 decimals_) external { - if (msg.sender != _initializer || _initialized) { + function initialize(address owner, string memory tokenName_, string memory tokenSymbol_, uint8 tokenDecimals_) external { + if (msg.sender != initializer || initialized) { revert InvalidInitialization(); } - _initialized = true; + initialized = true; - _name = name_; - _symbol = symbol_; - _decimals = decimals_; + tokenName = tokenName_; + tokenSymbol = tokenSymbol_; + tokenDecimals = tokenDecimals_; - _setupRole(DEFAULT_ADMIN_ROLE, owner_); - _setupRole(MINTER_ROLE, owner_); + _setupRole(DEFAULT_ADMIN_ROLE, owner); + _setupRole(MINTER_ROLE, owner); } // @@ -56,11 +56,11 @@ contract ERC20Token is ERC20, AccessControl { /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _amount Amount of tokens to mint. + * @param to Address to mint tokens to. + * @param amount Amount of tokens to mint. */ - function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) { - _mint(_to, _amount); + function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { + _mint(to, amount); } // @@ -69,12 +69,12 @@ contract ERC20Token is ERC20, AccessControl { /** * Check interface support. - * @param _interfaceId Interface id + * @param interfaceId Interface id * @return True if supported */ - function supportsInterface(bytes4 _interfaceId) public view override returns (bool) { - return _interfaceId == type(IERC20).interfaceId || _interfaceId == type(IERC20Metadata).interfaceId - || AccessControl.supportsInterface(_interfaceId) || super.supportsInterface(_interfaceId); + function supportsInterface(bytes4 interfaceId) public view override returns (bool) { + return interfaceId == type(IERC20).interfaceId || interfaceId == type(IERC20Metadata).interfaceId + || AccessControl.supportsInterface(interfaceId) || super.supportsInterface(interfaceId); } // @@ -85,20 +85,20 @@ contract ERC20Token is ERC20, AccessControl { * Override the ERC20 name function. */ function name() public view override returns (string memory) { - return _name; + return tokenName; } /** * Override the ERC20 symbol function. */ function symbol() public view override returns (string memory) { - return _symbol; + return tokenSymbol; } /** * Override the ERC20 decimals function. */ function decimals() public view override returns (uint8) { - return _decimals; + return tokenDecimals; } } diff --git a/src/tokens/ERC20/ERC20TokenFactory.sol b/src/tokens/ERC20/ERC20TokenFactory.sol index 17d6eced..716cff51 100644 --- a/src/tokens/ERC20/ERC20TokenFactory.sol +++ b/src/tokens/ERC20/ERC20TokenFactory.sol @@ -6,32 +6,32 @@ import {IERC20TokenFactory} from "./IERC20TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC20TokenFactory is IERC20TokenFactory, ProxyDeployer { - address private immutable _implAddr; + address private immutable implAddr; /** * Creates an ERC-20 Token Factory. */ constructor() { ERC20Token proxyImpl = new ERC20Token(); - _implAddr = address(proxyImpl); + implAddr = address(proxyImpl); } /** * Creates an ERC-20 Token proxy. - * @param _owner The owner of the ERC-20 Token proxy - * @param _name The name of the ERC-20 Token proxy - * @param _symbol The symbol of the ERC-20 Token proxy - * @param _decimals The decimals of the ERC-20 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-20 Token proxy + * @param name The name of the ERC-20 Token proxy + * @param symbol The symbol of the ERC-20 Token proxy + * @param decimals The decimals of the ERC-20 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-20 Token Proxy - * @dev The provided `_salt` is hashed with the caller address for security. + * @dev The provided `salt` is hashed with the caller address for security. */ - function deploy(address _owner, string memory _name, string memory _symbol, uint8 _decimals, bytes32 _salt) + function deploy(address owner, string memory name, string memory symbol, uint8 decimals, bytes32 salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); - ERC20Token(proxyAddr).initialize(_owner, _name, _symbol, _decimals); + proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + ERC20Token(proxyAddr).initialize(owner, name, symbol, decimals); emit ERC20TokenDeployed(proxyAddr); return proxyAddr; } diff --git a/src/tokens/ERC20/IERC20TokenFactory.sol b/src/tokens/ERC20/IERC20TokenFactory.sol index 6fc3ae8f..4594e11b 100644 --- a/src/tokens/ERC20/IERC20TokenFactory.sol +++ b/src/tokens/ERC20/IERC20TokenFactory.sol @@ -10,14 +10,14 @@ interface IERC20TokenFactory { /** * Creates an ERC-20 Token proxy. - * @param _owner The owner of the ERC-20 Token proxy - * @param _name The name of the ERC-20 Token proxy - * @param _symbol The symbol of the ERC-20 Token proxy - * @param _decimals The decimals of the ERC-20 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-20 Token proxy + * @param name The name of the ERC-20 Token proxy + * @param symbol The symbol of the ERC-20 Token proxy + * @param decimals The decimals of the ERC-20 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-20 Token Proxy */ - function deploy(address _owner, string memory _name, string memory _symbol, uint8 _decimals, bytes32 _salt) + function deploy(address owner, string memory name, string memory symbol, uint8 decimals, bytes32 salt) external returns (address proxyAddr); } diff --git a/src/tokens/ERC721/ERC721Token.sol b/src/tokens/ERC721/ERC721Token.sol index b9e310f8..91ab8079 100644 --- a/src/tokens/ERC721/ERC721Token.sol +++ b/src/tokens/ERC721/ERC721Token.sol @@ -15,42 +15,42 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - string private baseURI; // Missing _ due to _baseURI() function in ERC721A - string private _name; - string private _symbol; + string private baseURI; + string private tokenName; + string private tokenSymbol; - address private immutable _initializer; - bool private _initialized; + address private immutable initializer; + bool private initialized; /** * Deploy contract. */ constructor() ERC721A("", "") { - _initializer = msg.sender; + initializer = msg.sender; } /** * Initialize contract. - * @param owner_ The owner of the contract - * @param name_ Name of the token - * @param symbol_ Symbol of the token + * @param owner The owner of the contract + * @param tokenName_ Name of the token + * @param tokenSymbol_ Symbol of the token * @param baseURI_ Base URI of the token * @dev This should be called immediately after deployment. */ - function initialize(address owner_, string memory name_, string memory symbol_, string memory baseURI_) external { - if (msg.sender != _initializer || _initialized) { + function initialize(address owner, string memory tokenName_, string memory tokenSymbol_, string memory baseURI_) external { + if (msg.sender != initializer || initialized) { revert InvalidInitialization(); } - _initialized = true; + initialized = true; - _name = name_; - _symbol = symbol_; + tokenName = tokenName_; + tokenSymbol = tokenSymbol_; baseURI = baseURI_; - _setupRole(DEFAULT_ADMIN_ROLE, owner_); - _setupRole(METADATA_ADMIN_ROLE, owner_); - _setupRole(MINTER_ROLE, owner_); - _setupRole(ROYALTY_ADMIN_ROLE, owner_); + _setupRole(DEFAULT_ADMIN_ROLE, owner); + _setupRole(METADATA_ADMIN_ROLE, owner); + _setupRole(MINTER_ROLE, owner); + _setupRole(ROYALTY_ADMIN_ROLE, owner); } // @@ -59,11 +59,11 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { /** * Mint tokens. - * @param _to Address to mint tokens to. - * @param _amount Amount of tokens to mint. + * @param to Address to mint tokens to. + * @param amount Amount of tokens to mint. */ - function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) { - _mint(_to, _amount); + function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { + _mint(to, amount); } // @@ -72,10 +72,10 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { /** * Update the base URL of token's URI. - * @param _baseMetadataURI New base URL of token's URI + * @param baseURI_ New base URL of token's URI */ - function setBaseMetadataURI(string memory _baseMetadataURI) external onlyRole(METADATA_ADMIN_ROLE) { - baseURI = _baseMetadataURI; + function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { + baseURI = baseURI_; } // @@ -84,18 +84,18 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { /** * Check interface support. - * @param _interfaceId Interface id + * @param interfaceId Interface id * @return True if supported */ - function supportsInterface(bytes4 _interfaceId) + function supportsInterface(bytes4 interfaceId) public view override (ERC721A, IERC721A, ERC2981Controlled) returns (bool) { - return _interfaceId == type(IERC721A).interfaceId || _interfaceId == type(IERC721AQueryable).interfaceId - || ERC721A.supportsInterface(_interfaceId) || ERC2981Controlled.supportsInterface(_interfaceId) - || super.supportsInterface(_interfaceId); + return interfaceId == type(IERC721A).interfaceId || interfaceId == type(IERC721AQueryable).interfaceId + || ERC721A.supportsInterface(interfaceId) || ERC2981Controlled.supportsInterface(interfaceId) + || super.supportsInterface(interfaceId); } // @@ -113,13 +113,13 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { * Override the ERC721A name function. */ function name() public view override (ERC721A, IERC721A) returns (string memory) { - return _name; + return tokenName; } /** * Override the ERC721A symbol function. */ function symbol() public view override (ERC721A, IERC721A) returns (string memory) { - return _symbol; + return tokenSymbol; } } diff --git a/src/tokens/ERC721/ERC721TokenFactory.sol b/src/tokens/ERC721/ERC721TokenFactory.sol index f11972fa..f2cdd7bd 100644 --- a/src/tokens/ERC721/ERC721TokenFactory.sol +++ b/src/tokens/ERC721/ERC721TokenFactory.sol @@ -6,32 +6,32 @@ import {IERC721TokenFactory} from "./IERC721TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC721TokenFactory is IERC721TokenFactory, ProxyDeployer { - address private immutable _implAddr; + address private immutable implAddr; /** * Creates an ERC-721 Token Factory. */ constructor() { ERC721Token proxyImpl = new ERC721Token(); - _implAddr = address(proxyImpl); + implAddr = address(proxyImpl); } /** * Creates an ERC-721 Token proxy. - * @param _owner The owner of the ERC-721 Token proxy - * @param _name The name of the ERC-721 Token proxy - * @param _symbol The symbol of the ERC-721 Token proxy - * @param _baseURI The base URI of the ERC-721 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-721 Token proxy + * @param name The name of the ERC-721 Token proxy + * @param symbol The symbol of the ERC-721 Token proxy + * @param baseURI The base URI of the ERC-721 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-721 Token Proxy - * @dev The provided `_salt` is hashed with the caller address for security. + * @dev The provided `salt` is hashed with the caller address for security. */ - function deploy(address _owner, string memory _name, string memory _symbol, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory symbol, string memory baseURI, bytes32 salt) external returns (address proxyAddr) { - proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, _salt))); - ERC721Token(proxyAddr).initialize(_owner, _name, _symbol, _baseURI); + proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + ERC721Token(proxyAddr).initialize(owner, name, symbol, baseURI); emit ERC721TokenDeployed(proxyAddr); return proxyAddr; } diff --git a/src/tokens/ERC721/IERC721TokenFactory.sol b/src/tokens/ERC721/IERC721TokenFactory.sol index ed78642b..3c44107e 100644 --- a/src/tokens/ERC721/IERC721TokenFactory.sol +++ b/src/tokens/ERC721/IERC721TokenFactory.sol @@ -10,14 +10,14 @@ interface IERC721TokenFactory { /** * Creates an ERC-721 Token proxy. - * @param _owner The owner of the ERC-721 Token proxy - * @param _name The name of the ERC-721 Token proxy - * @param _symbol The symbol of the ERC-721 Token proxy - * @param _baseURI The base URI of the ERC-721 Token proxy - * @param _salt The deployment salt + * @param owner The owner of the ERC-721 Token proxy + * @param name The name of the ERC-721 Token proxy + * @param symbol The symbol of the ERC-721 Token proxy + * @param baseURI The base URI of the ERC-721 Token proxy + * @param salt The deployment salt * @return proxyAddr The address of the ERC-721 Token Proxy */ - function deploy(address _owner, string memory _name, string memory _symbol, string memory _baseURI, bytes32 _salt) + function deploy(address owner, string memory name, string memory symbol, string memory baseURI, bytes32 salt) external returns (address proxyAddr); } diff --git a/src/tokens/common/ERC2981Controlled.sol b/src/tokens/common/ERC2981Controlled.sol index 17f7854a..92042583 100644 --- a/src/tokens/common/ERC2981Controlled.sol +++ b/src/tokens/common/ERC2981Controlled.sol @@ -19,25 +19,25 @@ abstract contract ERC2981Controlled is /** * Sets the royalty information that all ids in this contract will default to. - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @param receiver Address of who should be sent the royalty payment + * @param feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) */ - function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { - _setDefaultRoyalty(_receiver, _feeNumerator); + function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { + _setDefaultRoyalty(receiver, feeNumerator); } /** * Sets the royalty information that a given token id in this contract will use. - * @param _tokenId The token id to set the royalty information for - * @param _receiver Address of who should be sent the royalty payment - * @param _feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) + * @param tokenId The token id to set the royalty information for + * @param receiver Address of who should be sent the royalty payment + * @param feeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500) * @notice This overrides the default royalty information for this token id */ - function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) + function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) external onlyRole(ROYALTY_ADMIN_ROLE) { - _setTokenRoyalty(_tokenId, _receiver, _feeNumerator); + _setTokenRoyalty(tokenId, receiver, feeNumerator); } // @@ -46,17 +46,17 @@ abstract contract ERC2981Controlled is /** * Check interface support. - * @param _interfaceId Interface id + * @param interfaceId Interface id * @return True if supported */ - function supportsInterface(bytes4 _interfaceId) + function supportsInterface(bytes4 interfaceId) public view virtual override (ERC2981, AccessControl) returns (bool) { - return ERC2981.supportsInterface(_interfaceId) || AccessControl.supportsInterface(_interfaceId) - || super.supportsInterface(_interfaceId); + return ERC2981.supportsInterface(interfaceId) || AccessControl.supportsInterface(interfaceId) + || super.supportsInterface(interfaceId); } } From 194ec581128adfd40cef6494bdb58581d54ba7c3 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Fri, 9 Jun 2023 09:50:16 +1200 Subject: [PATCH 13/15] Add READMEs --- README.md | 39 ++++++++++++++++++++++++++- src/proxies/ERC1967/README.md | 27 +++++++++++++++++++ src/tokens/ERC1155/Packed/README.md | 41 +++++++++++++++++++++++++++++ src/tokens/ERC1155/README.md | 41 +++++++++++++++++++++++++++++ src/tokens/ERC20/README.md | 36 +++++++++++++++++++++++++ src/tokens/ERC721/README.md | 39 +++++++++++++++++++++++++++ src/tokens/common/README.md | 32 ++++++++++++++++++++++ 7 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 src/proxies/ERC1967/README.md create mode 100644 src/tokens/ERC1155/Packed/README.md create mode 100644 src/tokens/ERC1155/README.md create mode 100644 src/tokens/ERC20/README.md create mode 100644 src/tokens/ERC721/README.md create mode 100644 src/tokens/common/README.md diff --git a/README.md b/README.md index dfce5ec5..3f10a926 100644 --- a/README.md +++ b/README.md @@ -1 +1,38 @@ -# contracts-library \ No newline at end of file +# Sequence Contracts Library + +This repository provides a set of smart contracts to facilitate the creation and management of contracts deployable on EVM compatible chains, including ERC20, ERC721, and ERC1155 token standards. These contracts are designed for gas efficiency and reuse via proxy deployments. + +## Features + +* **ERC20TokenFactory**: Allows for the easy creation of new ERC20 tokens through a factory contract and also provides functionality for minting new tokens. + +* **ERC721TokenFactory**: Similar to the ERC20TokenFactory, but for ERC721 (non-fungible) tokens. It allows for the creation and minting of ERC721 tokens, and also supports ERC2981 royalty information. + +* **ERC1155TokenFactory**: A factory for creating ERC1155 tokens, which can represent semi-fungible items. This contract also supports minting and updating metadata, as well as ERC2981 royalty information. + +* **Common Token Functionality**: This contains contracts that can be used for additional functionalities, such as the `ERC2981Controlled` contract which provides a way to handle royalties in NFTs. + +* **Proxies**: This section contains contracts implementing ERC1967 compliant proxies for upgradeability. + +## Usage + +1. Clone the repository +2. Install dependencies with `yarn` +3. Compile the contracts with `yarn build` +4. Run tests with `yarn test` + +### Deployment + +```sh +yarn deploy +``` + +**Note:** The Factory contracts in this repository contain no state and are not ownable, as such they only need to be deployed once per network. The Factory contracts are then available to be used by anyone. + +## Dependencies + +The contracts in this repository are built with Solidity ^0.8.17 and use OpenZeppelin and Azuki contracts for standards implementation and additional functionalities such as access control. + +## License + +All contracts in this repository are released under the Apache-2.0 license. diff --git a/src/proxies/ERC1967/README.md b/src/proxies/ERC1967/README.md new file mode 100644 index 00000000..378ff8cc --- /dev/null +++ b/src/proxies/ERC1967/README.md @@ -0,0 +1,27 @@ +# ERC1967 Proxies + +This subsection of the repository contains the implementation of [ERC1967 proxy contracts](https://eips.ethereum.org/EIPS/eip-1967). ERC1967 defines a standard for storage slots of upgradeable smart contract proxies. These proxies delegate calls to an implementation contract, which allows the logic of the contract to be upgraded without changing the address of the contract. + +## Features + +* **IERC1967**: This interface defines the standard events emitted by ERC1967 proxies - `Upgraded`, `AdminChanged`, and `BeaconUpgraded`. + +* **Proxy**: This is the core contract that acts as a ERC1967 proxy. It contains logic to forward calls to an implementation contract, allowing the contract to change its behavior over time without changing its address. + +* **ProxyDeployer**: This contract provides a helper function for deploying new proxies. It contains the logic to compute the address of a proxy before it is deployed, as well as a function to check if an address is a contract. + +**Note:** The current implementations do not support upgradeable proxies. + +## Usage + +To use the contracts in this section, import the desired contracts from the "proxies/ERC1967" directory and use the provided functions to deploy and interact with proxy contracts. For example: + +```solidity +import {ProxyDeployer} from "./proxies/ERC1967/ProxyDeployer.sol"; + +contract MyContractFactory is ProxyDeployer { + function deployNewContract(address implementation) public returns (address) { + return _deployProxy(implementation, keccak256(abi.encode(msg.sender))); + } +} +``` diff --git a/src/tokens/ERC1155/Packed/README.md b/src/tokens/ERC1155/Packed/README.md new file mode 100644 index 00000000..670f5356 --- /dev/null +++ b/src/tokens/ERC1155/Packed/README.md @@ -0,0 +1,41 @@ +# ERC1155 Packed Contracts + +This subsection contains contracts related to the [ERC1155 token standard](https://eips.ethereum.org/EIPS/eip-1155). The implementation utilises the [0xSequence Packed Balance implementation](https://github.com/0xsequence/erc-1155/blob/master/SPECIFICATIONS.md#packed-balance) for gas efficiency. + +## ERC1155PackedToken + +This contract is a complete, ready-to-use implementation of the ERC-1155 token standard. It includes additional features from the ERC1155MintBurn, ERC1155Meta, and ERC1155Metadata contracts. These contracts provide minting capabilities, support for meta transactions, and metadata functionality. + +Meta transactions are provided by the [0xSequence ERC1155 library](https://github.com/0xsequence/erc-1155/blob/master/SPECIFICATIONS.md#meta-transactions). Please refer to library documentation for more information on meta transactions. + +The ERC1155PackedToken contract has a two-step deployment process. First, it's deployed with an empty constructor. After deployment, the `initialize` function must be called to set the owner, name, and base URI. This process is in place to support proxy deployments with the ERC1155PackedTokenFactory. + +### Functions + +* `initialize(address owner, string memory name_, string memory baseURI_)`: Initializes the token contract, setting the owner, name, and base URI. +* `mint(address to, uint256 tokenId, uint256 amount, bytes memory data)`: Mints the specified amount of tokens of a given ID to the specified address. This function is restricted to addresses with the Minter role. +* `batchMint(address to, uint256[] memory tokenIds, uint256[] memory amounts, bytes memory data)`: Mints specified amounts of tokens of given IDs to the specified address. This function is restricted to addresses with the Minter role. +* `setBaseMetadataURI(string memory baseURI_)`: Updates the base URI for the token metadata. This function is restricted to addresses with the Metadata Admin role. +* `setContractName(string memory name_)`: Updates the contract's name. This function is restricted to addresses with the Metadata Admin role. + +## ERC1155PackedTokenFactory + +This contract deploys ERC1155PackedToken contracts. It uses a proxy pattern to create new token instances to reduce gas costs. + +The deployment uses a `salt` which is combined with the caller's address for cross chain consistency and security. + +### Functions + +* `deploy(address owner, string memory name, string memory baseURI, bytes32 salt)`: Deploys a new ERC1155PackedToken proxy contract, initializes it, and emits an ERC1155PackedTokenDeployed event. + +## Usage + +To create a new ERC1155 token: + +1. Deploy the ERC1155PackedTokenFactory contract (or use an existing deployment). +2. Call the `deploy` function on the factory, providing the desired parameters. +3. A new ERC1155PackedToken contract will be created and initialized, ready for use. + +## Dependencies + +This repository relies on the ERC1155, ERC1155MintBurn, ERC1155Meta, ERC1155Metadata contracts from 0xSequence for core ERC-1155 functionality, AccessControl from OpenZeppelin for role base permissions and the ERC2981Controlled contract for handling of royalties. diff --git a/src/tokens/ERC1155/README.md b/src/tokens/ERC1155/README.md new file mode 100644 index 00000000..e1ba95c4 --- /dev/null +++ b/src/tokens/ERC1155/README.md @@ -0,0 +1,41 @@ +# ERC1155 Contracts + +This subsection contains contracts related to the [ERC1155 token standard](https://eips.ethereum.org/EIPS/eip-1155). + +## ERC1155Token + +This contract is a complete, ready-to-use implementation of the ERC-1155 token standard. It includes additional features from the ERC1155MintBurn, ERC1155Meta, and ERC1155Metadata contracts. These contracts provide minting capabilities, support for meta transactions, and metadata functionality. + +Meta transactions are provided by the [0xSequence ERC1155 library](https://github.com/0xsequence/erc-1155/blob/master/SPECIFICATIONS.md#meta-transactions). Please refer to library documentation for more information on meta transactions. + +The ERC1155Token contract has a two-step deployment process. First, it's deployed with an empty constructor. After deployment, the `initialize` function must be called to set the owner, name, and base URI. This process is in place to support proxy deployments with the ERC1155TokenFactory. + +### Functions + +* `initialize(address owner, string memory name_, string memory baseURI_)`: Initializes the token contract, setting the owner, name, and base URI. +* `mint(address to, uint256 tokenId, uint256 amount, bytes memory data)`: Mints the specified amount of tokens of a given ID to the specified address. This function is restricted to addresses with the Minter role. +* `batchMint(address to, uint256[] memory tokenIds, uint256[] memory amounts, bytes memory data)`: Mints specified amounts of tokens of given IDs to the specified address. This function is restricted to addresses with the Minter role. +* `setBaseMetadataURI(string memory baseURI_)`: Updates the base URI for the token metadata. This function is restricted to addresses with the Metadata Admin role. +* `setContractName(string memory name_)`: Updates the contract's name. This function is restricted to addresses with the Metadata Admin role. + +## ERC1155TokenFactory + +This contract deploys ERC1155Token contracts. It uses a proxy pattern to create new token instances to reduce gas costs. + +The deployment uses a `salt` which is combined with the caller's address for cross chain consistency and security. + +### Functions + +* `deploy(address owner, string memory name, string memory baseURI, bytes32 salt)`: Deploys a new ERC1155Token proxy contract, initializes it, and emits an ERC1155TokenDeployed event. + +## Usage + +To create a new ERC1155 token: + +1. Deploy the ERC1155TokenFactory contract (or use an existing deployment). +2. Call the `deploy` function on the factory, providing the desired parameters. +3. A new ERC1155Token contract will be created and initialized, ready for use. + +## Dependencies + +This repository relies on the ERC1155, ERC1155MintBurn, ERC1155Meta, ERC1155Metadata contracts from 0xSequence for core ERC-1155 functionality, AccessControl from OpenZeppelin for role base permissions and the ERC2981Controlled contract for handling of royalties. diff --git a/src/tokens/ERC20/README.md b/src/tokens/ERC20/README.md new file mode 100644 index 00000000..879d44be --- /dev/null +++ b/src/tokens/ERC20/README.md @@ -0,0 +1,36 @@ +# ERC20 Contracts + +This subsection contains contracts related to the [ERC20 token standard](https://eips.ethereum.org/EIPS/eip-20). + +## ERC20Token + +This contract is a complete, ready-to-use implementation of the ERC-20 token standard. It includes role based access control features from the [OpenZeppelin AccessControl](https://docs.openzeppelin.com/contracts/4.x/access-control) contract, providing control over minting operations. Please refer to OpenZeppelin documentation for more information on AccessControl. + +The ERC20Token contract has a two-step deployment process. First, it's deployed with an empty constructor. After deployment, the `initialize` function must be called to set the owner, token name, symbol, and decimals. This process is in place to support proxy deployments with the ERC20TokenFactory. + +### Functions + +* `initialize(address owner, string memory tokenName_, string memory tokenSymbol_, uint8 tokenDecimals_)`: Initializes the token contract, setting the owner, name, symbol, and number of decimals. +* `mint(address to, uint256 amount)`: Mints the given amount of tokens toP the specified address. This function is restricted to addresses with the Minter role. + +## ERC20TokenFactory + +This contract deploys ERC20Token contracts. It uses a proxy pattern to create new token instances to reduce gas costs. + +The deployment uses a `salt` which is combined with the caller's address for cross chain consistency and security. + +### Functions + +* `deploy(address owner, string memory name, string memory symbol, uint8 decimals, bytes32 salt)`: Deploys a new ERC20Token proxy contract, initializes it, and emits an ERC20TokenDeployed event. + +## Usage + +To create a new ERC20 token: + +1. Deploy the ERC20TokenFactory contract (or use an existing deployment). +2. Call the `deploy` function on the factory, providing the desired parameters. +3. A new ERC20Token contract will be created and initialized, ready for use. + +## Dependencies + +This repo relies on the OpenZeppelin Contracts library, particularly the ERC20, IERC20, IERC20Metadata, and AccessControl contracts, which provide core ERC-20 functionality and secure access control mechanisms. diff --git a/src/tokens/ERC721/README.md b/src/tokens/ERC721/README.md new file mode 100644 index 00000000..89fd7d7d --- /dev/null +++ b/src/tokens/ERC721/README.md @@ -0,0 +1,39 @@ +# ERC721 Contracts + +This subsection contains contracts related to the [ERC721 token standard](https://eips.ethereum.org/EIPS/eip-721). + +## ERC721Token + +This contract is a complete, ready-to-use implementation of the ERC-721 token standard. It leverages the [Azuki ERC-721A implementation](https://www.erc721a.org/) for gas efficiency. It includes role based access control features from the [OpenZeppelin AccessControl](https://docs.openzeppelin.com/contracts/4.x/access-control) contract, providing control over minting operations and metadata administration. Please refer to OpenZeppelin documentation for more information on AccessControl. + +The ERC721Token contract has a two-step deployment process. First, it's deployed with an empty constructor. After deployment, the `initialize` function must be called to set the owner, token name, symbol, and base URI. This process is in place to support proxy deployments with the ERC721TokenFactory. + +The contract supports the [ERC2981 token royalty standard](https://eips.ethereum.org/EIPS/eip-2981) via the ERC2981Controlled contract. Please refer to the ERC2981Controlled documentation for more information on token royalty. + +### Functions + +* `initialize(address owner, string memory tokenName_, string memory tokenSymbol_, string memory baseURI_)`: Initializes the token contract, setting the owner, name, symbol, and base URI. +* `mint(address to, uint256 amount)`: Mints the given amount of tokens to the specified address. This function is restricted to addresses with the Minter role. +* `setBaseMetadataURI(string memory baseURI_)`: Updates the base URI for the token metadata. This function is restricted to addresses with the Metadata Admin role. + +## ERC721TokenFactory + +This contract deploys ERC721Token contracts. It uses a proxy pattern to create new token instances to reduce gas costs. + +The deployment uses a `salt` which is combined with the caller's address for cross chain consistency and security. + +### Functions + +* `deploy(address owner, string memory name, string memory symbol, string memory baseURI, bytes32 salt)`: Deploys a new ERC721Token proxy contract, initializes it, and emits an ERC721TokenDeployed event. + +## Usage + +To create a new ERC721 token: + +1. Deploy the ERC721TokenFactory contract (or use an existing deployment). +2. Call the `deploy` function on the factory, providing the desired parameters. +3. A new ERC721Token contract will be created and initialized, ready for use. + +## Dependencies + +This repo relies on the ERC721A, IERC721A, ERC721AQueryable, and IERC721AQueryable contracts from Azuki for core ERC-721 functionality, AccessControl from OpenZeppelin for role base permissions and the ERC2981Controlled contract for handling of royalties. diff --git a/src/tokens/common/README.md b/src/tokens/common/README.md new file mode 100644 index 00000000..e3277d6a --- /dev/null +++ b/src/tokens/common/README.md @@ -0,0 +1,32 @@ +# Common Token Functionality + +This section contains common contracts that can be used for additional functionality beyond the base token standards. + +## ERC2981Controlled + +The `ERC2981Controlled` contract is an implementation of the [ERC2981 token royalty standard](https://eips.ethereum.org/EIPS/eip-2981), which provides a standardized way to handle royalties in NFTs and SFTs. + +This contract allows the royalty information for the contract as a whole, or individual token IDs, to be updated by users with the `ROYALTY_ADMIN_ROLE`. + +### Functions + +* `setDefaultRoyalty(address receiver, uint96 feeNumerator)`: Sets the default royalty information for all token IDs in the contract. The `receiver` is the address that will receive royalty payments, and the `feeNumerator` is the royalty fee expressed in basis points (e.g., 15% would be 1500). This function is restricted to users with the `ROYALTY_ADMIN_ROLE`. +* `setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator)`: Sets the royalty information for a specific token ID, overriding the default royalty information for that token ID. The parameters are the same as in `setDefaultRoyalty`. This function is restricted to users with the `ROYALTY_ADMIN_ROLE`. + +### Usage + +To use this contract, it should be inherited by the main token contract. For example: + +```solidity +contract MyNFT is ERC721, ERC2981Controlled { + // ... +} +``` + +After that, the royalty information can be set and updated by users with the `ROYALTY_ADMIN_ROLE`. + +Alternatively, use the `ERC721Token` or `ERC1155Token` implementations which already extend this contract. + +### Dependencies + +The `ERC2981Controlled` contract depends on OpenZeppelin's `ERC2981` and `AccessControl` contracts. `ERC2981` provides the basic royalty-related functionality according to the standard, while `AccessControl` provides a flexible system of access control based on roles. From a35815a95b1790ec30bf2386bd0fa5b1417da412 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Fri, 9 Jun 2023 10:58:36 +1200 Subject: [PATCH 14/15] Add deploy script --- .env.example | 3 ++ README.md | 8 +++ package.json | 2 + scripts/deploy.ts | 133 ++++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 5 ++ 5 files changed, 151 insertions(+) create mode 100644 .env.example create mode 100644 scripts/deploy.ts diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..81486b9d --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +PRIVATE_KEY= +RPC_URL= + diff --git a/README.md b/README.md index 3f10a926..1e263d10 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,14 @@ This repository provides a set of smart contracts to facilitate the creation and ### Deployment +Copy `.env.example` to `.env` and set your wallet configuration. + +```sh +cp .env.example .env +``` + +Then run the deployment script. + ```sh yarn deploy ``` diff --git a/package.json b/package.json index cc3612da..307f9f7c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "license": "Apache-2.0", "scripts": { "build": "ts-node scripts/build.ts", + "deploy": "ts-node scripts/deploy.ts", "test": "forge test", "lint:init": "husky install", "lint:sol": "solhint \"./src/**/*.sol\" \"./tests/**/*.sol\"", @@ -35,6 +36,7 @@ }, "devDependencies": { "@types/node": "^20.1.0", + "dotenv": "^16.1.4", "husky": "^8.0.3", "lint-staged": "^13.2.2", "solhint": "^3.4.1", diff --git a/scripts/deploy.ts b/scripts/deploy.ts new file mode 100644 index 00000000..0bec1d96 --- /dev/null +++ b/scripts/deploy.ts @@ -0,0 +1,133 @@ +import { readFile } from 'fs/promises' +import { join } from 'path' +import { BUILD_DIR, DEPLOYABLE_CONTRACT_NAMES } from './constants' +import { config as dotenvConfig } from 'dotenv' +import { + ContractFactory, + ContractTransaction, + Signer, + Wallet, + ethers, +} from 'ethers' +import { JsonRpcProvider } from '@ethersproject/providers' + +dotenvConfig() + +const { PRIVATE_KEY, RPC_URL } = process.env + +const MAX_GAS_LIMIT = 6000000 + +const singletonFactoryFactory = { + address: '0xce0042B868300000d44A59004Da54A005ffdcf9f', + abi: [ + { + constant: false, + inputs: [ + { + internalType: 'bytes', + type: 'bytes', + }, + { + internalType: 'bytes32', + type: 'bytes32', + }, + ], + name: 'deploy', + outputs: [ + { + internalType: 'address payable', + type: 'address', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ], +} + +const main = async () => { + if (!PRIVATE_KEY || !RPC_URL) { + throw new Error('Environment vars not set') + } + + // Prep deployer wallet + const provider = new JsonRpcProvider(RPC_URL) + const wallet = new Wallet(PRIVATE_KEY, provider) + + // Create deployer factory + const singletonFactory = new ethers.Contract( + singletonFactoryFactory.address, + singletonFactoryFactory.abi, + wallet, + ) + + // Get deployment files from build dir + for (const solFile of DEPLOYABLE_CONTRACT_NAMES) { + console.log(`Deploying ${solFile}`) + + // Create contract for deployment + const compilerOutput = JSON.parse( + await readFile(join(BUILD_DIR, `${solFile}.json`), 'utf8'), + ) + class MyContractFactory extends ContractFactory { + constructor(signer?: Signer) { + super(compilerOutput.abi, compilerOutput.bytecode.object, signer) + } + } + const contract = new MyContractFactory(wallet) + const contractCode = contract.getDeployTransaction().data + if (!contractCode) { + throw new Error(`${solFile} did not return contract code`) + } + + // Check if already deployed + const address = ethers.utils.getAddress( + ethers.utils.hexDataSlice( + ethers.utils.keccak256( + ethers.utils.solidityPack( + ['bytes1', 'address', 'bytes32', 'bytes32'], + [ + '0xff', + singletonFactory.address, + ethers.constants.HashZero, + ethers.utils.keccak256(contractCode), + ], + ), + ), + 12, + ), + ) + + if (ethers.utils.arrayify(await provider.getCode(address)).length > 0) { + console.log( + `Skipping ${solFile} because it has been deployed at ${address}`, + ) + continue + } + + const tx: ContractTransaction = await singletonFactory.deploy( + contractCode, + ethers.constants.HashZero, + { + gasLimit: MAX_GAS_LIMIT, + }, + ) + await tx.wait() + + if (ethers.utils.arrayify(await provider.getCode(address)).length === 0) { + throw new Error(`failed to deploy ${solFile}`) + } + + console.log(`Deployed ${solFile} at ${address}`) + } +} + +main() + .then(() => { + console.log('Done') + }) + .catch(err => { + console.error(err) + process.exit(1) + }) diff --git a/yarn.lock b/yarn.lock index aaa018cc..56213ca5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -725,6 +725,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +dotenv@^16.1.4: + version "16.1.4" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.1.4.tgz#67ac1a10cd9c25f5ba604e4e08bc77c0ebe0ca8c" + integrity sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" From 8de75f4e7b6bdbe4c611dcdc2113a727271ff776 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Tue, 20 Jun 2023 09:18:30 +1200 Subject: [PATCH 15/15] Variable names --- src/proxies/ERC1967/Proxy.sol | 13 +++--- src/proxies/ERC1967/ProxyDeployer.sol | 31 +++++++------- src/tokens/ERC1155/ERC1155Token.sol | 32 +++++++------- src/tokens/ERC1155/ERC1155TokenFactory.sol | 6 +-- .../ERC1155/Packed/ERC1155PackedToken.sol | 32 +++++++------- .../Packed/ERC1155PackedTokenFactory.sol | 6 +-- src/tokens/ERC20/ERC20Token.sol | 36 ++++++++-------- src/tokens/ERC20/ERC20TokenFactory.sol | 6 +-- src/tokens/ERC721/ERC721Token.sol | 42 +++++++++---------- src/tokens/ERC721/ERC721TokenFactory.sol | 6 +-- src/utils/StorageSlot.sol | 16 +++---- 11 files changed, 114 insertions(+), 112 deletions(-) diff --git a/src/proxies/ERC1967/Proxy.sol b/src/proxies/ERC1967/Proxy.sol index 1cb44d61..0bd22b2a 100644 --- a/src/proxies/ERC1967/Proxy.sol +++ b/src/proxies/ERC1967/Proxy.sol @@ -19,20 +19,20 @@ contract Proxy is IERC1967 { * Forward calls to the proxy implementation contract. */ receive() external payable { - proxy(); + _proxy(); } /** * Forward calls to the proxy implementation contract. */ fallback() external payable { - proxy(); + _proxy(); } /** * Forward calls to the proxy implementation contract. */ - function proxy() private { + function _proxy() private { address target = _getImplementation(); assembly { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) @@ -48,15 +48,16 @@ contract Proxy is IERC1967 { /** * Set the implementation address. + * @param _implementation The address of the implementation contract. */ - function _setImplementation(address implementation) internal { - StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = implementation; + function _setImplementation(address _implementation) internal { + StorageSlot._getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation; } /** * Returns the address of the current implementation. */ function _getImplementation() internal view returns (address) { - return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; + return StorageSlot._getAddressSlot(IMPLEMENTATION_SLOT).value; } } diff --git a/src/proxies/ERC1967/ProxyDeployer.sol b/src/proxies/ERC1967/ProxyDeployer.sol index e590c4f7..f2aa6e84 100644 --- a/src/proxies/ERC1967/ProxyDeployer.sol +++ b/src/proxies/ERC1967/ProxyDeployer.sol @@ -5,18 +5,19 @@ import {ProxyDeployerErrors} from "./ProxyDeployerErrors.sol"; import {Proxy} from "./Proxy.sol"; abstract contract ProxyDeployer is ProxyDeployerErrors { + /** * Creates a proxy contract for a given implementation - * @param implAddr The address of the proxy implementation - * @param salt The deployment salt + * @param _implAddr The address of the proxy implementation + * @param _salt The deployment salt * @return proxyAddr The address of the deployed proxy */ - function _deployProxy(address implAddr, bytes32 salt) internal returns (address proxyAddr) { - bytes memory code = _getProxyCode(implAddr); + function _deployProxy(address _implAddr, bytes32 _salt) internal returns (address proxyAddr) { + bytes memory code = _getProxyCode(_implAddr); // Deploy it assembly { // solhint-disable-line no-inline-assembly - proxyAddr := create2(0, add(code, 32), mload(code), salt) + proxyAddr := create2(0, add(code, 32), mload(code), _salt) } if (proxyAddr == address(0)) { revert ProxyCreationFailed(); @@ -37,35 +38,35 @@ abstract contract ProxyDeployer is ProxyDeployerErrors { /** * Predict the deployed wrapper proxy address for a given implementation. - * @param code The code of the wrapper implementation - * @param salt The deployment salt + * @param _code The code of the wrapper implementation + * @param _salt The deployment salt * @return proxyAddr The address of the deployed wrapper */ - function _predictProxyAddress(bytes memory code, bytes32 salt) private view returns (address proxyAddr) { + function _predictProxyAddress(bytes memory _code, bytes32 _salt) private view returns (address proxyAddr) { address deployer = address(this); - bytes32 data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(code))); + bytes32 data = keccak256(abi.encodePacked(bytes1(0xff), deployer, _salt, keccak256(_code))); return address(uint160(uint256(data))); } /** * Returns the code of the proxy contract for a given implementation - * @param implAddr The address of the proxy implementation + * @param _implAddr The address of the proxy implementation * @return code The code of the proxy contract */ - function _getProxyCode(address implAddr) private pure returns (bytes memory code) { - return abi.encodePacked(type(Proxy).creationCode, abi.encode(implAddr)); + function _getProxyCode(address _implAddr) private pure returns (bytes memory code) { + return abi.encodePacked(type(Proxy).creationCode, abi.encode(_implAddr)); } /** * Checks if an address is a contract - * @param addr The address to check + * @param _addr The address to check * @return result True if the address is a contract */ - function _isContract(address addr) internal view returns (bool result) { + function _isContract(address _addr) internal view returns (bool result) { uint256 csize; // solhint-disable-next-line no-inline-assembly assembly { - csize := extcodesize(addr) + csize := extcodesize(_addr) } return csize != 0; } diff --git a/src/tokens/ERC1155/ERC1155Token.sol b/src/tokens/ERC1155/ERC1155Token.sol index c27e085d..943ae5f4 100644 --- a/src/tokens/ERC1155/ERC1155Token.sol +++ b/src/tokens/ERC1155/ERC1155Token.sol @@ -15,31 +15,31 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - address private immutable initializer; - bool private initialized; + address private immutable _initializer; + bool private _initialized; /** * Initialize contract. */ constructor() ERC1155Metadata("", "") { - initializer = msg.sender; + _initializer = msg.sender; } /** * Initialize the contract. * @param owner Owner address. - * @param name_ Token name. - * @param baseURI_ Base URI for token metadata. + * @param tokenName Token name. + * @param tokenBaseURI Base URI for token metadata. * @dev This should be called immediately after deployment. */ - function initialize(address owner, string memory name_, string memory baseURI_) public { - if (msg.sender != initializer || initialized) { + function initialize(address owner, string memory tokenName, string memory tokenBaseURI) public { + if (msg.sender != _initializer || _initialized) { revert InvalidInitialization(); } - initialized = true; + _initialized = true; - name = name_; - baseURI = baseURI_; + name = tokenName; + baseURI = tokenBaseURI; _setupRole(DEFAULT_ADMIN_ROLE, owner); _setupRole(MINTER_ROLE, owner); @@ -82,18 +82,18 @@ contract ERC1155Token is ERC1155MintBurn, ERC1155Meta, ERC1155Metadata, ERC2981C /** * Update the base URL of token's URI. - * @param baseURI_ New base URL of token's URI + * @param tokenBaseURI New base URL of token's URI */ - function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { - _setBaseMetadataURI(baseURI_); + function setBaseMetadataURI(string memory tokenBaseURI) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(tokenBaseURI); } /** * Update the name of the contract. - * @param name_ New contract name + * @param tokenName New contract name */ - function setContractName(string memory name_) external onlyRole(METADATA_ADMIN_ROLE) { - _setContractName(name_); + function setContractName(string memory tokenName) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(tokenName); } // diff --git a/src/tokens/ERC1155/ERC1155TokenFactory.sol b/src/tokens/ERC1155/ERC1155TokenFactory.sol index 3c54a808..564503da 100644 --- a/src/tokens/ERC1155/ERC1155TokenFactory.sol +++ b/src/tokens/ERC1155/ERC1155TokenFactory.sol @@ -6,14 +6,14 @@ import {IERC1155TokenFactory} from "./IERC1155TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC1155TokenFactory is IERC1155TokenFactory, ProxyDeployer { - address private immutable implAddr; + address private immutable _implAddr; /** * Creates an ERC-1155 Token Factory. */ constructor() { ERC1155Token proxyImpl = new ERC1155Token(); - implAddr = address(proxyImpl); + _implAddr = address(proxyImpl); } /** @@ -29,7 +29,7 @@ contract ERC1155TokenFactory is IERC1155TokenFactory, ProxyDeployer { external returns (address proxyAddr) { - proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, salt))); ERC1155Token(proxyAddr).initialize(owner, name, baseURI); emit ERC1155TokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol index 71b91d3a..f0ba0980 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedToken.sol @@ -23,31 +23,31 @@ contract ERC1155PackedToken is bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); - address private immutable initializer; - bool private initialized; + address private immutable _initializer; + bool private _initialized; /** * Initialize contract. */ constructor() ERC1155Metadata("", "") { - initializer = msg.sender; + _initializer = msg.sender; } /** * Initialize the contract. * @param owner Owner address. - * @param name_ Token name. - * @param baseURI_ Base URI for token metadata. + * @param tokenName Token name. + * @param tokenBaseURI Base URI for token metadata. * @dev This should be called immediately after deployment. */ - function initialize(address owner, string memory name_, string memory baseURI_) public { - if (msg.sender != initializer || initialized) { + function initialize(address owner, string memory tokenName, string memory tokenBaseURI) public { + if (msg.sender != _initializer || _initialized) { revert InvalidInitialization(); } - initialized = true; + _initialized = true; - name = name_; - baseURI = baseURI_; + name = tokenName; + baseURI = tokenBaseURI; _setupRole(DEFAULT_ADMIN_ROLE, owner); _setupRole(MINTER_ROLE, owner); @@ -90,18 +90,18 @@ contract ERC1155PackedToken is /** * Update the base URL of token's URI. - * @param baseURI_ New base URL of token's URI + * @param tokenBaseURI New base URL of token's URI */ - function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { - _setBaseMetadataURI(baseURI_); + function setBaseMetadataURI(string memory tokenBaseURI) external onlyRole(METADATA_ADMIN_ROLE) { + _setBaseMetadataURI(tokenBaseURI); } /** * Update the name of the contract. - * @param name_ New contract name + * @param tokenName New contract name */ - function setContractName(string memory name_) external onlyRole(METADATA_ADMIN_ROLE) { - _setContractName(name_); + function setContractName(string memory tokenName) external onlyRole(METADATA_ADMIN_ROLE) { + _setContractName(tokenName); } // diff --git a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol index 9f483f7b..9581a985 100644 --- a/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol +++ b/src/tokens/ERC1155/Packed/ERC1155PackedTokenFactory.sol @@ -6,14 +6,14 @@ import {IERC1155PackedTokenFactory} from "./IERC1155PackedTokenFactory.sol"; import {ProxyDeployer} from "../../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC1155PackedTokenFactory is IERC1155PackedTokenFactory, ProxyDeployer { - address private immutable implAddr; + address private immutable _implAddr; /** * Creates an ERC-1155 Token Factory. */ constructor() { ERC1155PackedToken proxyImpl = new ERC1155PackedToken(); - implAddr = address(proxyImpl); + _implAddr = address(proxyImpl); } /** @@ -29,7 +29,7 @@ contract ERC1155PackedTokenFactory is IERC1155PackedTokenFactory, ProxyDeployer external returns (address proxyAddr) { - proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, salt))); ERC1155PackedToken(proxyAddr).initialize(owner, name, baseURI); emit ERC1155PackedTokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC20/ERC20Token.sol b/src/tokens/ERC20/ERC20Token.sol index 308579f3..9d53711b 100644 --- a/src/tokens/ERC20/ERC20Token.sol +++ b/src/tokens/ERC20/ERC20Token.sol @@ -14,37 +14,37 @@ error InvalidInitialization(); contract ERC20Token is ERC20, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - string private tokenName; - string private tokenSymbol; - uint8 private tokenDecimals; + string private _tokenName; + string private _tokenSymbol; + uint8 private _tokenDecimals; - address private immutable initializer; - bool private initialized; + address private immutable _initializer; + bool private _initialized; /** * Deploy contract. */ constructor() ERC20("", "") { - initializer = msg.sender; + _initializer = msg.sender; } /** * Initialize contract. * @param owner The owner of the contract - * @param tokenName_ Name of the token - * @param tokenSymbol_ Symbol of the token - * @param tokenDecimals_ Number of decimals + * @param tokenName Name of the token + * @param tokenSymbol Symbol of the token + * @param tokenDecimals Number of decimals * @dev This should be called immediately after deployment. */ - function initialize(address owner, string memory tokenName_, string memory tokenSymbol_, uint8 tokenDecimals_) external { - if (msg.sender != initializer || initialized) { + function initialize(address owner, string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) external { + if (msg.sender != _initializer || _initialized) { revert InvalidInitialization(); } - initialized = true; + _initialized = true; - tokenName = tokenName_; - tokenSymbol = tokenSymbol_; - tokenDecimals = tokenDecimals_; + _tokenName = tokenName; + _tokenSymbol = tokenSymbol; + _tokenDecimals = tokenDecimals; _setupRole(DEFAULT_ADMIN_ROLE, owner); _setupRole(MINTER_ROLE, owner); @@ -85,20 +85,20 @@ contract ERC20Token is ERC20, AccessControl { * Override the ERC20 name function. */ function name() public view override returns (string memory) { - return tokenName; + return _tokenName; } /** * Override the ERC20 symbol function. */ function symbol() public view override returns (string memory) { - return tokenSymbol; + return _tokenSymbol; } /** * Override the ERC20 decimals function. */ function decimals() public view override returns (uint8) { - return tokenDecimals; + return _tokenDecimals; } } diff --git a/src/tokens/ERC20/ERC20TokenFactory.sol b/src/tokens/ERC20/ERC20TokenFactory.sol index 716cff51..7329f16e 100644 --- a/src/tokens/ERC20/ERC20TokenFactory.sol +++ b/src/tokens/ERC20/ERC20TokenFactory.sol @@ -6,14 +6,14 @@ import {IERC20TokenFactory} from "./IERC20TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC20TokenFactory is IERC20TokenFactory, ProxyDeployer { - address private immutable implAddr; + address private immutable _implAddr; /** * Creates an ERC-20 Token Factory. */ constructor() { ERC20Token proxyImpl = new ERC20Token(); - implAddr = address(proxyImpl); + _implAddr = address(proxyImpl); } /** @@ -30,7 +30,7 @@ contract ERC20TokenFactory is IERC20TokenFactory, ProxyDeployer { external returns (address proxyAddr) { - proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, salt))); ERC20Token(proxyAddr).initialize(owner, name, symbol, decimals); emit ERC20TokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/tokens/ERC721/ERC721Token.sol b/src/tokens/ERC721/ERC721Token.sol index 91ab8079..d1618f0b 100644 --- a/src/tokens/ERC721/ERC721Token.sol +++ b/src/tokens/ERC721/ERC721Token.sol @@ -15,37 +15,37 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { bytes32 public constant METADATA_ADMIN_ROLE = keccak256("METADATA_ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - string private baseURI; - string private tokenName; - string private tokenSymbol; + string private _tokenBaseURI; + string private _tokenName; + string private _tokenSymbol; - address private immutable initializer; - bool private initialized; + address private immutable _initializer; + bool private _initialized; /** * Deploy contract. */ constructor() ERC721A("", "") { - initializer = msg.sender; + _initializer = msg.sender; } /** * Initialize contract. * @param owner The owner of the contract - * @param tokenName_ Name of the token - * @param tokenSymbol_ Symbol of the token - * @param baseURI_ Base URI of the token + * @param tokenName Name of the token + * @param tokenSymbol Symbol of the token + * @param tokenBaseURI Base URI of the token * @dev This should be called immediately after deployment. */ - function initialize(address owner, string memory tokenName_, string memory tokenSymbol_, string memory baseURI_) external { - if (msg.sender != initializer || initialized) { + function initialize(address owner, string memory tokenName, string memory tokenSymbol, string memory tokenBaseURI) external { + if (msg.sender != _initializer || _initialized) { revert InvalidInitialization(); } - initialized = true; + _initialized = true; - tokenName = tokenName_; - tokenSymbol = tokenSymbol_; - baseURI = baseURI_; + _tokenName = tokenName; + _tokenSymbol = tokenSymbol; + _tokenBaseURI = tokenBaseURI; _setupRole(DEFAULT_ADMIN_ROLE, owner); _setupRole(METADATA_ADMIN_ROLE, owner); @@ -72,10 +72,10 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { /** * Update the base URL of token's URI. - * @param baseURI_ New base URL of token's URI + * @param tokenBaseURI New base URL of token's URI */ - function setBaseMetadataURI(string memory baseURI_) external onlyRole(METADATA_ADMIN_ROLE) { - baseURI = baseURI_; + function setBaseMetadataURI(string memory tokenBaseURI) external onlyRole(METADATA_ADMIN_ROLE) { + _tokenBaseURI = tokenBaseURI; } // @@ -106,20 +106,20 @@ contract ERC721Token is ERC721AQueryable, ERC2981Controlled { * Override the ERC721A baseURI function. */ function _baseURI() internal view override returns (string memory) { - return baseURI; + return _tokenBaseURI; } /** * Override the ERC721A name function. */ function name() public view override (ERC721A, IERC721A) returns (string memory) { - return tokenName; + return _tokenName; } /** * Override the ERC721A symbol function. */ function symbol() public view override (ERC721A, IERC721A) returns (string memory) { - return tokenSymbol; + return _tokenSymbol; } } diff --git a/src/tokens/ERC721/ERC721TokenFactory.sol b/src/tokens/ERC721/ERC721TokenFactory.sol index f2cdd7bd..1f444917 100644 --- a/src/tokens/ERC721/ERC721TokenFactory.sol +++ b/src/tokens/ERC721/ERC721TokenFactory.sol @@ -6,14 +6,14 @@ import {IERC721TokenFactory} from "./IERC721TokenFactory.sol"; import {ProxyDeployer} from "../../proxies/ERC1967/ProxyDeployer.sol"; contract ERC721TokenFactory is IERC721TokenFactory, ProxyDeployer { - address private immutable implAddr; + address private immutable _implAddr; /** * Creates an ERC-721 Token Factory. */ constructor() { ERC721Token proxyImpl = new ERC721Token(); - implAddr = address(proxyImpl); + _implAddr = address(proxyImpl); } /** @@ -30,7 +30,7 @@ contract ERC721TokenFactory is IERC721TokenFactory, ProxyDeployer { external returns (address proxyAddr) { - proxyAddr = _deployProxy(implAddr, keccak256(abi.encode(msg.sender, salt))); + proxyAddr = _deployProxy(_implAddr, keccak256(abi.encode(msg.sender, salt))); ERC721Token(proxyAddr).initialize(owner, name, symbol, baseURI); emit ERC721TokenDeployed(proxyAddr); return proxyAddr; diff --git a/src/utils/StorageSlot.sol b/src/utils/StorageSlot.sol index d0c0ef3a..b45b9fb2 100644 --- a/src/utils/StorageSlot.sol +++ b/src/utils/StorageSlot.sol @@ -29,36 +29,36 @@ library StorageSlot { /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ - function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + function _getAddressSlot(bytes32 _slot) internal pure returns (AddressSlot storage r) { assembly { // solhint-disable-line no-inline-assembly - r.slot := slot + r.slot := _slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ - function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + function _getBooleanSlot(bytes32 _slot) internal pure returns (BooleanSlot storage r) { assembly { // solhint-disable-line no-inline-assembly - r.slot := slot + r.slot := _slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ - function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + function _getBytes32Slot(bytes32 _slot) internal pure returns (Bytes32Slot storage r) { assembly { // solhint-disable-line no-inline-assembly - r.slot := slot + r.slot := _slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ - function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + function _getUint256Slot(bytes32 _slot) internal pure returns (Uint256Slot storage r) { assembly { // solhint-disable-line no-inline-assembly - r.slot := slot + r.slot := _slot } } }