diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..1cfa77d4 Binary files /dev/null and b/.DS_Store differ diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..388ac4fa --- /dev/null +++ b/.env.example @@ -0,0 +1,18 @@ +# Config +INFURA_KEY= +PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000001 +ETHERSCAN_API_KEY= + +# Verax Testnet Config +ROUTER_ADDRESS=0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5 +PORTAL_REGISTRY_ADDRESS=0x506f88a5Ca8D5F001f2909b029738A40042e42a6 +SCHEMA_REGISTRY_ADDRESS=0xB2c4Da1f8F08A0CA25862509E5431289BE2b598B +MODULE_REGISTRY_ADDRESS=0x1a20b2CFA134686306436D2c9f778D7eC6c43A43 +ATTESTATION_REGISTRY_ADDRESS=0xC765F28096F6121C2F2b82D35A4346280164428b + +# Verax Mainnet Config +#ROUTER_ADDRESS=0x4d3a380A03f3a18A5dC44b01119839D8674a552E +#PORTAL_REGISTRY_ADDRESS=0xd5d61e4ECDf6d46A63BfdC262af92544DFc19083 +#SCHEMA_REGISTRY_ADDRESS=0x0f95dCec4c7a93F2637eb13b655F2223ea036B59 +#MODULE_REGISTRY_ADDRESS=0xf851513A732996F22542226341748f3C9978438f +#ATTESTATION_REGISTRY_ADDRESS=0x3de3893aa4Cdea029e84e75223a152FD08315138 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..71abdfae --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @alainncls @fdemiramon @satyajeetkolhapure @orbmis @0xEillo diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..e15ba6a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] " +labels: "" +assignees: "" +--- + +**Describe the bug** A clear and concise description of what the bug is. + +**To Reproduce** Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** A clear and concise description of what you expected to happen. + +**Screenshots** If applicable, add screenshots to help explain your problem. + +**Additional context** Add any other context about the problem here, e.g. transaction hash, network name etc. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..8bc3b00f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: "" +assignees: "" +--- + +**Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem +is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** A clear and concise description of any alternative solutions or features +you've considered. + +**Additional context** Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..09fc0990 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,17 @@ +## What does this PR do? + +### Related ticket + +Fixes # + +### Type of change + +- [ ] Chore +- [ ] Bug fix +- [ ] New feature +- [ ] Documentation update + +## Check list + +- [ ] Unit tests for any smart contract change +- [ ] Contracts and functions are documented diff --git a/.github/workflows/releaser.yaml b/.github/workflows/releaser.yaml new file mode 100644 index 00000000..b50b7b87 --- /dev/null +++ b/.github/workflows/releaser.yaml @@ -0,0 +1,21 @@ +--- +name: New version releaser + +on: + workflow_dispatch: + +jobs: + release: + if: github.actor == 'alainncls' || github.actor == 'fdemiramon' || github.actor == 'satyajeetkolhapure' || github.actor == 'orbmis' || github.actor == '0xEillo' + + runs-on: ubuntu-latest + + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + fetch-depth: 0 + token: ${{ secrets.PROD_RELEASER_GH_TOKEN }} + + - name: "Run release script" + run: ./release.sh diff --git a/.github/workflows/smart-contracts-test.yml b/.github/workflows/smart-contracts-test.yml new file mode 100644 index 00000000..1fa06d7e --- /dev/null +++ b/.github/workflows/smart-contracts-test.yml @@ -0,0 +1,163 @@ +name: Smart Contracts Test + +on: + pull_request: + branches: + - main + - dev + - release/* + push: + branches: + - main + - dev + - release/* + +env: + FOUNDRY_PROFILE: ci + +jobs: + lint: + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + + - name: "Install Pnpm" + uses: "pnpm/action-setup@v2" + with: + version: "8" + + - name: "Install Node.js" + uses: "actions/setup-node@v3" + with: + cache: "pnpm" + node-version: "lts/*" + + - name: "Install the Node.js dependencies" + run: "pnpm install" + + - name: "Lint the contracts" + run: "pnpm lint" + + - name: "Add lint summary" + run: | + echo "## Lint result" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed" >> $GITHUB_STEP_SUMMARY + + build: + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + submodules: "recursive" + + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + + - name: "Show the Foundry config" + run: "forge config" + + - name: "Produce a build" + run: "forge build" + + - name: "Add build summary" + run: | + echo "## Build result" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed" >> $GITHUB_STEP_SUMMARY + + test-unit: + env: + FOUNDRY_FUZZ_RUNS: "5000" + needs: [ "lint", "build" ] + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + submodules: "recursive" + + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + + - name: "Run the unit tests" + run: "forge test --match-path \"test/*\"" + + - name: "Add test summary" + run: | + echo "## Unit tests result" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed" >> $GITHUB_STEP_SUMMARY + + coverage: + needs: [ "lint", "build" ] + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + submodules: "recursive" + + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + + - name: "Generate the coverage report using the unit tests" + run: "forge coverage --match-path \"test/**/*.sol\" --report lcov" + + - name: "Upload coverage report to Codecov" + uses: "codecov/codecov-action@v3" + with: + files: "./lcov.info" + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + verbose: true + + - name: "Check test coverage" + uses: "terencetcf/github-actions-lcov-minimum-coverage-checker@v1" + with: + coverage-file: lcov.info + minimum-coverage: 96 + + - name: "Add coverage summary" + run: | + echo "## Coverage result" >> $GITHUB_STEP_SUMMARY + echo "✅ Uploaded to Codecov" >> $GITHUB_STEP_SUMMARY + + upgradeability: + needs: [ "lint", "build" ] + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + submodules: "recursive" + + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + + - name: "Install Pnpm" + uses: "pnpm/action-setup@v2" + with: + version: "8" + + - name: "Install Node.js" + uses: "actions/setup-node@v3" + with: + cache: "pnpm" + node-version: "lts/*" + + - name: "Install the Node.js dependencies" + run: "pnpm install" + + - name: "Produce a build" + run: "forge build" + + - name: "Check contracts upgradeability" + run: "pnpm run check:upgradeability:ci" + + - name: "Add upgradeability summary" + run: | + echo "## Upgradeability check result" >> $GITHUB_STEP_SUMMARY + echo "✅ Contracts are upgradeable" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ed40f473 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env + +# Modules +node_modules + +# IDE +.idea +.vscode + +# Coverage +lcov.info +coverage + +# Hardhat +cache_hardhat +artifacts +typechain-types +.openzeppelin diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..b6afba79 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "lib/forge-std"] + branch = "v1" + path = "lib/forge-std" + url = "https://github.com/foundry-rs/forge-std" +[submodule "lib/openzeppelin-contracts-upgradeable"] + branch = "release-v4.9" + path = "lib/openzeppelin-contracts-upgradeable" + url = "https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..247c370d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +pnpm run prettier:write +pnpm run lint +pnpm run test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..79c2615d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,23 @@ +# directories +.github/workflows +broadcast +cache +coverage +docs +lib +node_modules +out +out-optimized +out-svg +artifacts +cache_hardhat + +# files +*.env +*.log +.DS_Store +.pnp.* +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..babf76ce --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,13 @@ +bracketSpacing: true +printWidth: 120 +proseWrap: "always" +singleQuote: false +tabWidth: 2 +trailingComma: "all" +useTabs: false +overrides: + - files: "*.svg" + options: + parser: "html" +plugins: + - "prettier-plugin-solidity" diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 00000000..108f3996 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,17 @@ +{ + "extends": "solhint:recommended", + "rules": { + "avoid-low-level-calls": "off", + "code-complexity": ["error", 9], + "compiler-version": ["error", "0.8.21"], + "contract-name-camelcase": "off", + "const-name-snakecase": "off", + "func-name-mixedcase": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 123], + "named-parameters-mapping": "warn", + "no-empty-blocks": "off", + "not-rely-on-time": "off", + "var-name-mixedcase": "off" + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ac819fff --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2023 ConsenSys Software, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index ad49deed..c5439d57 100644 --- a/README.md +++ b/README.md @@ -1 +1,246 @@ -# linea-attestation-registry \ No newline at end of file +## Verax (Linea Attestation Registry) + +**Linea Attestation Registry is a set of contracts that allows anyone to read and write attestations of any type and any +subject.** + +## Foundry Installation + +**Using Foundryup** + +Foundryup is the Foundry toolchain installer. Open your terminal and run the following command: + +`curl -L https://foundry.paradigm.xyz | bash` This will install Foundryup, then simply follow the instructions +on-screen, which will make the foundryup command available in your CLI. + +Running foundryup by itself will install the latest (nightly) precompiled binaries: forge, cast, anvil and chisel. See +foundryup --help for more options, like installing from a specific version or commit. + +ℹ️ Note + +If you're on Windows, you will need to install and use Git BASH or WSL, as your terminal, since Foundryup currently does +not support Powershell or Cmd. + +For more details on installation, see the [installation guide](https://book.getfoundry.sh/getting-started/installation) +in the book. + +If you're experiencing any issues while installing, check out the [FAQ](https://book.getfoundry.sh/faq). + +## Forge - build and test + +We can build the project with forge build: + +``` +$ forge build +[⠊] Compiling... +[⠘] Compiling 22 files with 0.8.20 +[⠒] Solc 0.8.20 finished in 2.97s +Compiler run successful! +``` + +And run the tests with forge test: + +``` +$ forge test +No files changed, compilation skipped + +Running 2 tests for test/Counter.t.sol:CounterTest +[PASS] testIncrement() (gas: 28334) +[PASS] testSetNumber(uint256) (runs: 256, μ: 27398, ~: 28409) +Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 10.42ms +Ran 1 test suites: 2 tests passed, 0 failed, 0 skipped (2 total tests) +``` + +## Deployment - using Anvil + +Anvil is a local testnet node shipped with Foundry. You can use it for testing your contracts from frontends or for +interacting over RPC. Anvil is part of the Foundry suite and is installed alongside forge, cast and chisel. + +**Step 1 : Run a local node using Anvil** + +To run a local node, simply type anvil. You should see a list of accounts and private keys available for use, as well as +the address and port the node is listening on. + +``` +$ anvil + + + _ _ + (_) | | + __ _ _ __ __ __ _ | | + / _` | | '_ \ \ \ / / | | | | + | (_| | | | | | \ V / | | | | + \__,_| |_| |_| \_/ |_| |_| + + 0.1.0 (02e430c 2023-07-21T00:20:33.193960100Z) + https://github.com/foundry-rs/foundry + +Available Accounts +================== + +(0) "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" (10000.000000000000000000 ETH) +(1) "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" (10000.000000000000000000 ETH) +(2) "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" (10000.000000000000000000 ETH) +(3) "0x90F79bf6EB2c4f870365E785982E1f101E93b906" (10000.000000000000000000 ETH) +(4) "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65" (10000.000000000000000000 ETH) +(5) "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" (10000.000000000000000000 ETH) +(6) "0x976EA74026E726554dB657fA54763abd0C3a0aa9" (10000.000000000000000000 ETH) +(7) "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955" (10000.000000000000000000 ETH) +(8) "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f" (10000.000000000000000000 ETH) +(9) "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" (10000.000000000000000000 ETH) + +Private Keys +================== + +(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +(1) 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d +(2) 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a +(3) 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6 +(4) 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a +(5) 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba +(6) 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e +(7) 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 +(8) 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 +(9) 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 + +Wallet +================== +Mnemonic: test test test test test test test test test test test junk +Derivation path: m/44'/60'/0'/0/ + + +Chain ID +================== + +31337 +1000000000 + +Gas Limit +================== + +30000000 + +Genesis Timestamp +================== + +1689949885 + +Listening on 127.0.0.1:8545 +``` + +Anvil is highly configurable. You can run anvil -h to see all the configuration options. + +Some basic options are: + +``` +# Number of dev accounts to generate and configure. [default: 10] +anvil -a, --accounts + +# The EVM hardfork to use. [default: latest] +anvil --hardfork + +# Port number to listen on. [default: 8545] +anvil -p, --port +``` + +**Step 2 : Deployment** + +Forge can deploy smart contracts to a given network with the forge create command. + +Forge can deploy only one contract at a time. + +To deploy on Anvil local node use `forge create` command with RPC url and any private key provided by anvil local node +mentioned above. + +e.g. + +``` +forge create --rpc-url http://127.0.0.1:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 src/Counter.sol:Counter +[⠆] Compiling... +No files changed, compilation skipped +Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +Deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3 +Transaction hash: 0x15b25752da1dfd458b92069248825ce959f5be104f974d62b4ae95050710325d +``` + +## Verax contracts deployment + +### On the Linea Goerli testnet: + +1. Copy the `.env.example` file to a `.env` file +2. Fill it with your Infura key +3. Add your private key +4. To verify the contracts on Etherscan, also add your Etherscan API key +5. Deploy every contract via the `pnpm run deploy:all:goerli` command +6. Note down the summarized addresses (proxies), and the total logs can be of interest too +7. Gather the first list of issuers addresses +8. Set the issuers via the PortalRegistry’s `setIssuers` method +9. Deploy an instance of DefaultPortal via the PortalRegistry’s `deployDefaultPortal` method and note down its address +10. Verify this contract via `npx hardhat verify --network linea-goerli ADDRESS` +11. _Optional_: Deploy some valid modules via the `pnpm run deploy:CorrectModule:goerli` command and note down their + addresses +12. _Optional_: Deploy an invalid module via the `pnpm run deploy:IncorrectModule:goerli` command and note down its + address + +### On the Linea mainnet: + +1. Copy the `.env.example` file to a `.env` file +2. Fill it with your Infura key +3. Add your private key +4. To verify the contracts on Etherscan, also add your Etherscan API key +5. Deploy every contract via the `pnpm run deploy:all` command +6. Note down the summarized addresses (proxies), and the total logs can be of interest too +7. Gather the first list of issuers addresses +8. Set the issuers via the PortalRegistry’s `setIssuers` method +9. Deploy an instance of DefaultPortal via the PortalRegistry’s `deployDefaultPortal` method and note down its address +10. Verify this contract via `npx hardhat verify --network linea ADDRESS` +11. _Optional_: Deploy some valid modules via the `pnpm run deploy:CorrectModule` command and note down their addresses +12. _Optional_: Deploy an invalid module via the `pnpm run deploy:IncorrectModule` command and note down its address + +## Verax contract upgrade + +### On the Linea Goerli testnet: + +1. Check your `.env` file contains the address of the proxy for the contract you want to upgrade +2. Run `pnpm run upgrade:ContractName:goerli`, replacing `ContractName` with the contract you want to upgrade +3. Alternatively, you can upgrade all contracts at once via `pnpm run upgrade:all:goerli` + +### On the Linea mainnet: + +1. Check your `.env` file contains the address of the proxy for the contract you want to upgrade +2. Run `pnpm run upgrade:ContractName`, replacing `ContractName` with the contract you want to upgrade +3. Alternatively, you can upgrade all contracts at once via `pnpm run upgrade:all` + +## Contracts addresses + +### Testnet + +- Router = + [0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5](https://goerli.lineascan.build/address/0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5) +- AttestationRegistry = + [0xC765F28096F6121C2F2b82D35A4346280164428b](https://goerli.lineascan.build/address/0xC765F28096F6121C2F2b82D35A4346280164428b) +- ModuleRegistry = + [0x1a20b2CFA134686306436D2c9f778D7eC6c43A43](https://goerli.lineascan.build/address/0x1a20b2CFA134686306436D2c9f778D7eC6c43A43) +- PortalRegistry = + [0x506f88a5Ca8D5F001f2909b029738A40042e42a6](https://goerli.lineascan.build/address/0x506f88a5Ca8D5F001f2909b029738A40042e42a6) +- SchemaRegistry = + [0xB2c4Da1f8F08A0CA25862509E5431289BE2b598B](https://goerli.lineascan.build/address/0xB2c4Da1f8F08A0CA25862509E5431289BE2b598B) + +### Mainnet + +- Router = + [0x4d3a380A03f3a18A5dC44b01119839D8674a552E](https://lineascan.build/address/0x4d3a380A03f3a18A5dC44b01119839D8674a552E) +- AttestationRegistry = + [0x3de3893aa4Cdea029e84e75223a152FD08315138](https://lineascan.build/address/0x3de3893aa4Cdea029e84e75223a152FD08315138) +- ModuleRegistry = + [0xf851513A732996F22542226341748f3C9978438f](https://lineascan.build/address/0xf851513A732996F22542226341748f3C9978438f) +- PortalRegistry = + [0xd5d61e4ECDf6d46A63BfdC262af92544DFc19083](https://lineascan.build/address/0xd5d61e4ECDf6d46A63BfdC262af92544DFc19083) +- SchemaRegistry = + [0x0f95dCec4c7a93F2637eb13b655F2223ea036B59](https://lineascan.build/address/0x0f95dCec4c7a93F2637eb13b655F2223ea036B59) + +## Relationship schemas id's + +### Testnet & Mainnet + +- Relationship schema id = 0x89bd76e17fd84df8e1e448fa1b46dd8d97f7e8e806552b003f8386a5aebcb9f0 +- namedGraphRelationship schema id = 0x5003a7832fa2734780a5bf6a1f3940b84c0c66a398e62dd4e7f183fdbc7da6ee diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 00000000..9ed221ce --- /dev/null +++ b/foundry.toml @@ -0,0 +1,13 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +[rpc_endpoints] +linea_goerli = "${LINEA_GOERLI_RPC_URL}" + +[etherscan] +linea_goerli = { key = "${ETHERSCAN_API_KEY}" } + + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/hardhat.config.ts b/hardhat.config.ts new file mode 100644 index 00000000..f1c98413 --- /dev/null +++ b/hardhat.config.ts @@ -0,0 +1,61 @@ +import { HardhatUserConfig } from "hardhat/config"; +import "@nomicfoundation/hardhat-toolbox"; +import "@nomicfoundation/hardhat-foundry"; +import "@openzeppelin/hardhat-upgrades"; +import dotenv from "dotenv"; + +dotenv.config({ path: "./.env" }); + +const config: HardhatUserConfig = { + solidity: { + compilers: [ + { + version: "0.8.21", + settings: { + evmVersion: "paris", + }, + }, + ], + }, + defaultNetwork: "linea-goerli", + networks: { + hardhat: {}, + "linea-goerli": { + url: `https://linea-goerli.infura.io/v3/${process.env.INFURA_KEY ?? ""}`, + accounts: [process.env.PRIVATE_KEY ?? ""], + }, + linea: { + url: `https://linea-mainnet.infura.io/v3/${process.env.INFURA_KEY ?? ""}`, + accounts: [process.env.PRIVATE_KEY ?? ""], + }, + }, + paths: { + sources: "./src", + }, + etherscan: { + apiKey: { + "linea-goerli": process.env.ETHERSCAN_API_KEY ?? "", + linea: process.env.ETHERSCAN_API_KEY ?? "", + }, + customChains: [ + { + network: "linea-goerli", + chainId: 59140, + urls: { + apiURL: "https://api-testnet.lineascan.build/api", + browserURL: "https://goerli.lineascan.build", + }, + }, + { + network: "linea", + chainId: 59144, + urls: { + apiURL: "https://api.lineascan.build/api", + browserURL: "https://lineascan.build", + }, + }, + ], + }, +}; + +export default config; diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 00000000..74cfb77e --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 74cfb77e308dd188d2f58864aaf44963ae6b88b1 diff --git a/lib/openzeppelin-contracts-upgradeable b/lib/openzeppelin-contracts-upgradeable new file mode 160000 index 00000000..f34a3a7e --- /dev/null +++ b/lib/openzeppelin-contracts-upgradeable @@ -0,0 +1 @@ +Subproject commit f34a3a7e5a1d698d87d517fda698d48286310bee diff --git a/package.json b/package.json new file mode 100644 index 00000000..cb3218b2 --- /dev/null +++ b/package.json @@ -0,0 +1,75 @@ +{ + "name": "linea-attestation-registry", + "version": "0.0.1", + "description": "Core smart contracts to read and write attestations on Linea", + "keywords": [ + "linea-attestation-registry", + "blockchain", + "attestation", + "ethereum", + "foundry", + "smart-contracts", + "solidity" + ], + "repository": "github.com/Consensys/linea-attestation-registry", + "license": "ISC", + "author": "Consensys", + "files": [ + "src" + ], + "scripts": { + "build": "forge build", + "check:upgradeability": "npx hardhat run script/checkUpgradeability.ts", + "check:upgradeability:ci": "cp .env.example .env && pnpm run check:upgradeability", + "clean": "rm -rf lcov.info coverage .openzeppelin artifacts cache_hardhat cache out typechain-types", + "deploy:CorrectModule": "npx hardhat run --network linea script/deploy/deployCorrectModule.ts", + "deploy:CorrectModule:goerli": "npx hardhat run --network linea-goerli script/deploy/deployCorrectModule.ts", + "deploy:IncorrectModule": "npx hardhat run --network linea script/deploy/deployIncorrectModule.ts", + "deploy:IncorrectModule:goerli": "npx hardhat run --network linea-goerli script/deploy/deployIncorrectModule.ts", + "deploy:MsgSenderModule": "npx hardhat run --network linea script/deploy/deployMsgSenderModule.ts", + "deploy:MsgSenderModule:goerli": "npx hardhat run --network linea-goerli script/deploy/deployMsgSenderModule.ts", + "deploy:all": "npx hardhat run --network linea script/deploy/deployEverything.ts", + "deploy:all:goerli": "npx hardhat run --network linea-goerli script/deploy/deployEverything.ts", + "deploy:post": "npx hardhat run --network linea script/deploy/postDeployment.ts", + "deploy:post:goerli": "npx hardhat run --network linea-goerli script/deploy/postDeployment.ts", + "lint": "pnpm lint:sol && pnpm prettier:check", + "lint:sol": "pnpm solhint \"{script,src,test}/**/*.sol\"", + "prepare": "husky install", + "prettier:check": "prettier --check \"**/*.{json,md,svg,yml,sol}\"", + "prettier:write": "prettier --write \"**/*.{json,md,svg,yml,sol}\"", + "test": "forge test", + "upgrade:all": "pnpm run upgrade:AttestationRegistry && pnpm run upgrade:ModuleRegistry && pnpm run upgrade:PortalRegistry && pnpm run upgrade:Router && pnpm run upgrade:SchemaRegistry", + "upgrade:all:goerli": "pnpm run upgrade:AttestationRegistry:goerli && pnpm run upgrade:ModuleRegistry:goerli && pnpm run upgrade:PortalRegistry:goerli && pnpm run upgrade:Router:goerli && pnpm run upgrade:SchemaRegistry:goerli", + "upgrade:AttestationRegistry": "npx hardhat run --network linea script/upgrade/upgradeAttestationRegistry.ts", + "upgrade:AttestationRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeAttestationRegistry.ts", + "upgrade:ModuleRegistry": "npx hardhat run --network linea script/upgrade/upgradeModuleRegistry.ts", + "upgrade:ModuleRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeModuleRegistry.ts", + "upgrade:PortalRegistry": "npx hardhat run --network linea script/upgrade/upgradePortalRegistry.ts", + "upgrade:PortalRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradePortalRegistry.ts", + "upgrade:Router": "npx hardhat run --network linea script/upgrade/upgradeRouter.ts", + "upgrade:Router:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeRouter.ts", + "upgrade:SchemaRegistry": "npx hardhat run --network linea script/upgrade/upgradeSchemaRegistry.ts", + "upgrade:SchemaRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeSchemaRegistry.ts" + }, + "devDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-foundry": "^1.1.1", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@openzeppelin/hardhat-upgrades": "^2.2.1", + "dotenv": "^16.3.1", + "ethers": "^6.7.1", + "hardhat": "^2.17.2", + "husky": "^8.0.3", + "prettier": "^2.8.8", + "prettier-plugin-solidity": "^1.1.3", + "solhint": "^3.6.2", + "solhint-plugin-prettier": "^0.0.5" + }, + "pnpm": { + "overrides": { + "flat@<5.0.1": ">=5.0.1", + "tough-cookie@<4.1.3": ">=4.1.3", + "minimatch@<3.0.5": ">=3.0.5" + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..59721f27 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5579 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + flat@<5.0.1: '>=5.0.1' + tough-cookie@<4.1.3: '>=4.1.3' + minimatch@<3.0.5: '>=3.0.5' + +devDependencies: + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.4 + version: 3.0.4(ethers@6.7.1)(hardhat@2.17.2) + '@nomicfoundation/hardhat-foundry': + specifier: ^1.1.1 + version: 1.1.1(hardhat@2.17.2) + '@nomicfoundation/hardhat-toolbox': + specifier: ^3.0.0 + version: 3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.2)(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.5)(@types/mocha@10.0.1)(@types/node@20.5.7)(chai@4.3.8)(ethers@6.7.1)(hardhat-gas-reporter@1.0.9)(hardhat@2.17.2)(solidity-coverage@0.8.4)(ts-node@10.9.1)(typechain@8.3.1)(typescript@5.2.2) + '@openzeppelin/hardhat-upgrades': + specifier: ^2.2.1 + version: 2.2.1(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-verify@1.1.1)(ethers@6.7.1)(hardhat@2.17.2) + dotenv: + specifier: ^16.3.1 + version: 16.3.1 + ethers: + specifier: ^6.7.1 + version: 6.7.1 + hardhat: + specifier: ^2.17.2 + version: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + husky: + specifier: ^8.0.3 + version: 8.0.3 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + prettier-plugin-solidity: + specifier: ^1.1.3 + version: 1.1.3(prettier@2.8.8) + solhint: + specifier: ^3.6.2 + version: 3.6.2 + solhint-plugin-prettier: + specifier: ^0.0.5 + version: 0.0.5(prettier-plugin-solidity@1.1.3)(prettier@2.8.8) + +packages: + + /@adraffy/ens-normalize@1.9.2: + resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==} + dev: true + + /@aws-crypto/sha256-js@1.2.2: + resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==} + dependencies: + '@aws-crypto/util': 1.2.2 + '@aws-sdk/types': 3.398.0 + tslib: 1.14.1 + dev: true + + /@aws-crypto/util@1.2.2: + resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==} + dependencies: + '@aws-sdk/types': 3.398.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + dev: true + + /@aws-sdk/types@3.398.0: + resolution: {integrity: sha512-r44fkS+vsEgKCuEuTV+TIk0t0m5ZlXHNjSDYEUvzLStbbfUFiNus/YG4UCa0wOk9R7VuQI67badsvvPeVPCGDQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.2.2 + tslib: 2.6.2 + dev: true + + /@aws-sdk/util-utf8-browser@3.259.0: + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + dependencies: + tslib: 2.6.2 + dev: true + + /@babel/code-frame@7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.13 + chalk: 2.4.2 + dev: true + + /@babel/helper-validator-identifier@7.22.5: + resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight@7.22.13: + resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@chainsafe/as-sha256@0.3.1: + resolution: {integrity: sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==} + dev: true + + /@chainsafe/persistent-merkle-tree@0.4.2: + resolution: {integrity: sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==} + dependencies: + '@chainsafe/as-sha256': 0.3.1 + dev: true + + /@chainsafe/persistent-merkle-tree@0.5.0: + resolution: {integrity: sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==} + dependencies: + '@chainsafe/as-sha256': 0.3.1 + dev: true + + /@chainsafe/ssz@0.10.2: + resolution: {integrity: sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==} + dependencies: + '@chainsafe/as-sha256': 0.3.1 + '@chainsafe/persistent-merkle-tree': 0.5.0 + dev: true + + /@chainsafe/ssz@0.9.4: + resolution: {integrity: sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==} + dependencies: + '@chainsafe/as-sha256': 0.3.1 + '@chainsafe/persistent-merkle-tree': 0.4.2 + case: 1.6.3 + dev: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@ethereumjs/rlp@4.0.1: + resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /@ethereumjs/util@8.1.0: + resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} + engines: {node: '>=14'} + dependencies: + '@ethereumjs/rlp': 4.0.1 + ethereum-cryptography: 2.1.2 + micro-ftch: 0.3.1 + dev: true + + /@ethersproject/abi@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/abstract-provider@5.7.0: + resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + dev: true + + /@ethersproject/abstract-signer@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/address@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/base64@5.7.0: + resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + dependencies: + '@ethersproject/bytes': 5.7.0 + dev: true + + /@ethersproject/basex@5.7.0: + resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/properties': 5.7.0 + dev: true + + /@ethersproject/bignumber@5.7.0: + resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + bn.js: 5.2.1 + dev: true + + /@ethersproject/bytes@5.7.0: + resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/constants@5.7.0: + resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + dev: true + + /@ethersproject/contracts@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/hash@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/hdnode@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/json-wallets@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/keccak256@5.7.0: + resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + dependencies: + '@ethersproject/bytes': 5.7.0 + js-sha3: 0.8.0 + dev: true + + /@ethersproject/logger@5.7.0: + resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} + dev: true + + /@ethersproject/networks@5.7.1: + resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/pbkdf2@5.7.0: + resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/sha2': 5.7.0 + dev: true + + /@ethersproject/properties@5.7.0: + resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/providers@5.7.2: + resolution: {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.1 + '@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.1 + bech32: 1.1.4 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@ethersproject/random@5.7.0: + resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/rlp@5.7.0: + resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/sha2@5.7.0: + resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + hash.js: 1.1.7 + dev: true + + /@ethersproject/signing-key@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/solidity@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/strings@5.7.0: + resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/transactions@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/units@5.7.0: + resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: true + + /@ethersproject/wallet@5.7.0: + resolution: {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 + dev: true + + /@ethersproject/web@5.7.1: + resolution: {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 + dev: true + + /@ethersproject/wordlists@5.7.0: + resolution: {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 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@metamask/eth-sig-util@4.0.1: + resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} + engines: {node: '>=12.0.0'} + dependencies: + ethereumjs-abi: 0.6.8 + ethereumjs-util: 6.2.1 + ethjs-util: 0.1.6 + tweetnacl: 1.0.3 + tweetnacl-util: 0.15.1 + dev: true + + /@noble/curves@1.1.0: + resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} + dependencies: + '@noble/hashes': 1.3.1 + dev: true + + /@noble/hashes@1.1.2: + resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} + dev: true + + /@noble/hashes@1.2.0: + resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} + dev: true + + /@noble/hashes@1.3.1: + resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} + engines: {node: '>= 16'} + dev: true + + /@noble/secp256k1@1.7.1: + resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@nomicfoundation/ethereumjs-block@5.0.2: + resolution: {integrity: sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + ethereum-cryptography: 0.1.3 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-blockchain@7.0.2: + resolution: {integrity: sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-ethash': 3.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + abstract-level: 1.0.3 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + level: 8.0.0 + lru-cache: 5.1.1 + memory-level: 1.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-common@4.0.2: + resolution: {integrity: sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==} + dependencies: + '@nomicfoundation/ethereumjs-util': 9.0.2 + crc-32: 1.2.2 + dev: true + + /@nomicfoundation/ethereumjs-ethash@3.0.2: + resolution: {integrity: sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + abstract-level: 1.0.3 + bigint-crypto-utils: 3.3.0 + ethereum-cryptography: 0.1.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-evm@2.0.2: + resolution: {integrity: sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==} + engines: {node: '>=14'} + dependencies: + '@ethersproject/providers': 5.7.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + mcl-wasm: 0.7.9 + rustbn.js: 0.2.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-rlp@5.0.2: + resolution: {integrity: sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /@nomicfoundation/ethereumjs-statemanager@2.0.2: + resolution: {integrity: sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==} + dependencies: + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + ethers: 5.7.2 + js-sdsl: 4.4.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-trie@6.0.2: + resolution: {integrity: sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@types/readable-stream': 2.3.15 + ethereum-cryptography: 0.1.3 + readable-stream: 3.6.2 + dev: true + + /@nomicfoundation/ethereumjs-tx@5.0.2: + resolution: {integrity: sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==} + engines: {node: '>=14'} + dependencies: + '@chainsafe/ssz': 0.9.4 + '@ethersproject/providers': 5.7.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + ethereum-cryptography: 0.1.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@nomicfoundation/ethereumjs-util@9.0.2: + resolution: {integrity: sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==} + engines: {node: '>=14'} + dependencies: + '@chainsafe/ssz': 0.10.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + ethereum-cryptography: 0.1.3 + dev: true + + /@nomicfoundation/ethereumjs-vm@7.0.2: + resolution: {integrity: sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==} + engines: {node: '>=14'} + dependencies: + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + debug: 4.3.4(supports-color@8.1.1) + ethereum-cryptography: 0.1.3 + mcl-wasm: 0.7.9 + rustbn.js: 0.2.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /@nomicfoundation/hardhat-chai-matchers@2.0.2(@nomicfoundation/hardhat-ethers@3.0.4)(chai@4.3.8)(ethers@6.7.1)(hardhat@2.17.2): + resolution: {integrity: sha512-9Wu9mRtkj0U9ohgXYFbB/RQDa+PcEdyBm2suyEtsJf3PqzZEEjLUZgWnMjlFhATMk/fp3BjmnYVPrwl+gr8oEw==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.7.1)(hardhat@2.17.2) + '@types/chai-as-promised': 7.1.5 + chai: 4.3.8 + chai-as-promised: 7.1.1(chai@4.3.8) + deep-eql: 4.1.3 + ethers: 6.7.1 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + ordinal: 1.0.3 + dev: true + + /@nomicfoundation/hardhat-ethers@3.0.4(ethers@6.7.1)(hardhat@2.17.2): + resolution: {integrity: sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA==} + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + dependencies: + debug: 4.3.4(supports-color@8.1.1) + ethers: 6.7.1 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + lodash.isequal: 4.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@nomicfoundation/hardhat-foundry@1.1.1(hardhat@2.17.2): + resolution: {integrity: sha512-cXGCBHAiXas9Pg9MhMOpBVQCkWRYoRFG7GJJAph+sdQsfd22iRs5U5Vs9XmpGEQd1yEvYISQZMeE68Nxj65iUQ==} + peerDependencies: + hardhat: ^2.17.2 + dependencies: + chalk: 2.4.2 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + dev: true + + /@nomicfoundation/hardhat-network-helpers@1.0.9(hardhat@2.17.2): + resolution: {integrity: sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==} + peerDependencies: + hardhat: ^2.9.5 + dependencies: + ethereumjs-util: 7.1.5 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + dev: true + + /@nomicfoundation/hardhat-toolbox@3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.2)(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-network-helpers@1.0.9)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.5)(@types/mocha@10.0.1)(@types/node@20.5.7)(chai@4.3.8)(ethers@6.7.1)(hardhat-gas-reporter@1.0.9)(hardhat@2.17.2)(solidity-coverage@0.8.4)(ts-node@10.9.1)(typechain@8.3.1)(typescript@5.2.2): + resolution: {integrity: sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==} + peerDependencies: + '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-network-helpers': ^1.0.0 + '@nomicfoundation/hardhat-verify': ^1.0.0 + '@typechain/ethers-v6': ^0.4.0 + '@typechain/hardhat': ^8.0.0 + '@types/chai': ^4.2.0 + '@types/mocha': '>=9.1.0' + '@types/node': '>=12.0.0' + chai: ^4.2.0 + ethers: ^6.4.0 + hardhat: ^2.11.0 + hardhat-gas-reporter: ^1.0.8 + solidity-coverage: ^0.8.1 + ts-node: '>=8.0.0' + typechain: ^8.2.0 + typescript: '>=4.5.0' + dependencies: + '@nomicfoundation/hardhat-chai-matchers': 2.0.2(@nomicfoundation/hardhat-ethers@3.0.4)(chai@4.3.8)(ethers@6.7.1)(hardhat@2.17.2) + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.7.1)(hardhat@2.17.2) + '@nomicfoundation/hardhat-network-helpers': 1.0.9(hardhat@2.17.2) + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.17.2) + '@typechain/ethers-v6': 0.4.3(ethers@6.7.1)(typechain@8.3.1)(typescript@5.2.2) + '@typechain/hardhat': 8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.7.1)(hardhat@2.17.2)(typechain@8.3.1) + '@types/chai': 4.3.5 + '@types/mocha': 10.0.1 + '@types/node': 20.5.7 + chai: 4.3.8 + ethers: 6.7.1 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + hardhat-gas-reporter: 1.0.9(hardhat@2.17.2) + solidity-coverage: 0.8.4(hardhat@2.17.2) + ts-node: 10.9.1(@types/node@20.5.7)(typescript@5.2.2) + typechain: 8.3.1(typescript@5.2.2) + typescript: 5.2.2 + dev: true + + /@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.17.2): + resolution: {integrity: sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==} + peerDependencies: + hardhat: ^2.0.4 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + cbor: 8.1.0 + chalk: 2.4.2 + debug: 4.3.4(supports-color@8.1.1) + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + lodash.clonedeep: 4.5.0 + semver: 6.3.1 + table: 6.8.1 + undici: 5.23.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1: + resolution: {integrity: sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1: + resolution: {integrity: sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1: + resolution: {integrity: sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1: + resolution: {integrity: sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1: + resolution: {integrity: sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1: + resolution: {integrity: sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1: + resolution: {integrity: sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1: + resolution: {integrity: sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1: + resolution: {integrity: sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1: + resolution: {integrity: sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@nomicfoundation/solidity-analyzer@0.1.1: + resolution: {integrity: sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==} + engines: {node: '>= 12'} + optionalDependencies: + '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.1 + '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.1 + '@nomicfoundation/solidity-analyzer-freebsd-x64': 0.1.1 + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu': 0.1.1 + '@nomicfoundation/solidity-analyzer-linux-arm64-musl': 0.1.1 + '@nomicfoundation/solidity-analyzer-linux-x64-gnu': 0.1.1 + '@nomicfoundation/solidity-analyzer-linux-x64-musl': 0.1.1 + '@nomicfoundation/solidity-analyzer-win32-arm64-msvc': 0.1.1 + '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.1 + '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.1 + dev: true + + /@openzeppelin/defender-admin-client@1.48.0(debug@4.3.4): + resolution: {integrity: sha512-MN29JD6jA3PgOxF2tG0aZbMIwOCieYWkK9UbHCq1UzGPrMgGV9NVMUyVdqpv7Ynplwsjp5ZTBDOyttwvTlchHg==} + dependencies: + '@openzeppelin/defender-base-client': 1.48.0(debug@4.3.4) + axios: 1.5.0(debug@4.3.4) + ethers: 5.7.2 + lodash: 4.17.21 + node-fetch: 2.7.0 + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - utf-8-validate + dev: true + + /@openzeppelin/defender-base-client@1.48.0(debug@4.3.4): + resolution: {integrity: sha512-HFO87s010hRrMjyh2xYOCEAkLe21BfIbho7n5/kikA6A1ZgXi7MsEiqnQv1zP4bxMJgxGZ5b3t4tt6fWrakbag==} + dependencies: + amazon-cognito-identity-js: 6.3.5 + async-retry: 1.3.3 + axios: 1.5.0(debug@4.3.4) + lodash: 4.17.21 + node-fetch: 2.7.0 + transitivePeerDependencies: + - debug + - encoding + dev: true + + /@openzeppelin/hardhat-upgrades@2.2.1(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-verify@1.1.1)(ethers@6.7.1)(hardhat@2.17.2): + resolution: {integrity: sha512-Amlk2nhNpCfTCEovbqyarwBv4ZWmuiHHIcYfGy+FCSkkuSvQNVEJHoSl83Vgag+QhMtubdoggkYPqayxU46w1Q==} + hasBin: true + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^1.1.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + '@nomicfoundation/hardhat-verify': + optional: true + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.4(ethers@6.7.1)(hardhat@2.17.2) + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.17.2) + '@openzeppelin/defender-admin-client': 1.48.0(debug@4.3.4) + '@openzeppelin/defender-base-client': 1.48.0(debug@4.3.4) + '@openzeppelin/platform-deploy-client': 0.10.0(debug@4.3.4) + '@openzeppelin/upgrades-core': 1.28.0 + chalk: 4.1.2 + debug: 4.3.4(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + ethers: 6.7.1 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + proper-lockfile: 4.1.2 + undici: 5.23.0 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /@openzeppelin/platform-deploy-client@0.10.0(debug@4.3.4): + resolution: {integrity: sha512-jayQPeXqw4LnWIrNhNqgikJSre+n2NRrnEu76niSdVXc/faQkG3PmaHtRPJMFgsYxjjAiAfcMYyV95YBDuLexA==} + deprecated: '@openzeppelin/platform-deploy-client is deprecated. Please use @openzeppelin/defender-sdk-deploy-client' + dependencies: + '@ethersproject/abi': 5.7.0 + '@openzeppelin/defender-base-client': 1.48.0(debug@4.3.4) + axios: 1.5.0(debug@4.3.4) + lodash: 4.17.21 + node-fetch: 2.7.0 + transitivePeerDependencies: + - debug + - encoding + dev: true + + /@openzeppelin/upgrades-core@1.28.0: + resolution: {integrity: sha512-8RKlyg98Adv+46GxDaR0awL3R8bVCcQ27DcSEwrgWOp6siHh8sZg4a2l+2dhPl1510S6uBfhHSydMH5VX2BV5g==} + hasBin: true + dependencies: + cbor: 9.0.1 + chalk: 4.1.2 + compare-versions: 6.1.0 + debug: 4.3.4(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + minimist: 1.2.8 + proper-lockfile: 4.1.2 + solidity-ast: 0.4.52 + transitivePeerDependencies: + - supports-color + dev: true + + /@scure/base@1.1.3: + resolution: {integrity: sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==} + dev: true + + /@scure/bip32@1.1.5: + resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} + dependencies: + '@noble/hashes': 1.2.0 + '@noble/secp256k1': 1.7.1 + '@scure/base': 1.1.3 + dev: true + + /@scure/bip32@1.3.1: + resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} + dependencies: + '@noble/curves': 1.1.0 + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.3 + dev: true + + /@scure/bip39@1.1.1: + resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} + dependencies: + '@noble/hashes': 1.2.0 + '@scure/base': 1.1.3 + dev: true + + /@scure/bip39@1.2.1: + resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} + dependencies: + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.3 + dev: true + + /@sentry/core@5.30.0: + resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} + engines: {node: '>=6'} + dependencies: + '@sentry/hub': 5.30.0 + '@sentry/minimal': 5.30.0 + '@sentry/types': 5.30.0 + '@sentry/utils': 5.30.0 + tslib: 1.14.1 + dev: true + + /@sentry/hub@5.30.0: + resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} + engines: {node: '>=6'} + dependencies: + '@sentry/types': 5.30.0 + '@sentry/utils': 5.30.0 + tslib: 1.14.1 + dev: true + + /@sentry/minimal@5.30.0: + resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} + engines: {node: '>=6'} + dependencies: + '@sentry/hub': 5.30.0 + '@sentry/types': 5.30.0 + tslib: 1.14.1 + dev: true + + /@sentry/node@5.30.0: + resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} + engines: {node: '>=6'} + dependencies: + '@sentry/core': 5.30.0 + '@sentry/hub': 5.30.0 + '@sentry/tracing': 5.30.0 + '@sentry/types': 5.30.0 + '@sentry/utils': 5.30.0 + cookie: 0.4.2 + https-proxy-agent: 5.0.1 + lru_map: 0.3.3 + tslib: 1.14.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@sentry/tracing@5.30.0: + resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} + engines: {node: '>=6'} + dependencies: + '@sentry/hub': 5.30.0 + '@sentry/minimal': 5.30.0 + '@sentry/types': 5.30.0 + '@sentry/utils': 5.30.0 + tslib: 1.14.1 + dev: true + + /@sentry/types@5.30.0: + resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} + engines: {node: '>=6'} + dev: true + + /@sentry/utils@5.30.0: + resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} + engines: {node: '>=6'} + dependencies: + '@sentry/types': 5.30.0 + tslib: 1.14.1 + dev: true + + /@smithy/types@2.2.2: + resolution: {integrity: sha512-4PS0y1VxDnELGHGgBWlDksB2LJK8TG8lcvlWxIsgR+8vROI7Ms8h1P4FQUx+ftAX2QZv5g1CJCdhdRmQKyonyw==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: true + + /@solidity-parser/parser@0.14.5: + resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} + dependencies: + antlr4ts: 0.5.0-alpha.4 + dev: true + + /@solidity-parser/parser@0.16.1: + resolution: {integrity: sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==} + dependencies: + antlr4ts: 0.5.0-alpha.4 + dev: true + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@typechain/ethers-v6@0.4.3(ethers@6.7.1)(typechain@8.3.1)(typescript@5.2.2): + resolution: {integrity: sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==} + peerDependencies: + ethers: 6.x + typechain: ^8.3.1 + typescript: '>=4.7.0' + dependencies: + ethers: 6.7.1 + lodash: 4.17.21 + ts-essentials: 7.0.3(typescript@5.2.2) + typechain: 8.3.1(typescript@5.2.2) + typescript: 5.2.2 + dev: true + + /@typechain/hardhat@8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.7.1)(hardhat@2.17.2)(typechain@8.3.1): + resolution: {integrity: sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==} + peerDependencies: + '@typechain/ethers-v6': ^0.4.3 + ethers: ^6.1.0 + hardhat: ^2.9.9 + typechain: ^8.3.1 + dependencies: + '@typechain/ethers-v6': 0.4.3(ethers@6.7.1)(typechain@8.3.1)(typescript@5.2.2) + ethers: 6.7.1 + fs-extra: 9.1.0 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + typechain: 8.3.1(typescript@5.2.2) + dev: true + + /@types/bn.js@4.11.6: + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /@types/bn.js@5.1.1: + resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /@types/chai-as-promised@7.1.5: + resolution: {integrity: sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==} + dependencies: + '@types/chai': 4.3.5 + dev: true + + /@types/chai@4.3.5: + resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} + dev: true + + /@types/concat-stream@1.6.1: + resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /@types/form-data@0.0.33: + resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /@types/glob@7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 20.5.7 + dev: true + + /@types/lru-cache@5.1.1: + resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + dev: true + + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + + /@types/mocha@10.0.1: + resolution: {integrity: sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==} + dev: true + + /@types/node@10.17.60: + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + dev: true + + /@types/node@18.15.13: + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + dev: true + + /@types/node@20.5.7: + resolution: {integrity: sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==} + dev: true + + /@types/node@8.10.66: + resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} + dev: true + + /@types/pbkdf2@3.1.0: + resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /@types/prettier@2.7.3: + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true + + /@types/qs@6.9.8: + resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + dev: true + + /@types/readable-stream@2.3.15: + resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} + dependencies: + '@types/node': 20.5.7 + safe-buffer: 5.1.2 + dev: true + + /@types/secp256k1@4.0.3: + resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} + dependencies: + '@types/node': 20.5.7 + dev: true + + /abbrev@1.0.9: + resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} + dev: true + + /abstract-level@1.0.3: + resolution: {integrity: sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==} + engines: {node: '>=12'} + dependencies: + buffer: 6.0.3 + catering: 2.1.1 + is-buffer: 2.0.5 + level-supports: 4.0.1 + level-transcoder: 1.0.1 + module-error: 1.0.2 + queue-microtask: 1.2.3 + dev: true + + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + dev: true + + /adm-zip@0.4.16: + resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} + engines: {node: '>=0.3.0'} + dev: true + + /aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + dev: true + + /aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + dev: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + dev: true + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /amazon-cognito-identity-js@6.3.5: + resolution: {integrity: sha512-bRAiw6uQuttufRD0TFcrWvA5hxAgPIwNzM0crmWniPdkmCxRoa68yxRaViZUbwAcGu9YPLCLqM87b1060BRddw==} + dependencies: + '@aws-crypto/sha256-js': 1.2.2 + buffer: 4.9.2 + fast-base64-decode: 1.0.0 + isomorphic-unfetch: 3.1.0 + js-cookie: 2.2.1 + transitivePeerDependencies: + - encoding + dev: true + + /amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + requiresBuild: true + dev: true + optional: true + + /ansi-colors@3.2.3: + resolution: {integrity: sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==} + engines: {node: '>=6'} + dev: true + + /ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + dev: true + + /ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /antlr4@4.13.0: + resolution: {integrity: sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew==} + engines: {node: '>=16'} + dev: true + + /antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-back@3.1.0: + resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} + engines: {node: '>=6'} + dev: true + + /array-back@4.0.2: + resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} + engines: {node: '>=8'} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array.prototype.findlast@1.2.3: + resolution: {integrity: sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-shim-unscopables: 1.0.0 + get-intrinsic: 1.2.1 + dev: true + + /array.prototype.reduce@1.0.6: + resolution: {integrity: sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-array-method-boxes-properly: 1.0.0 + is-string: 1.0.7 + dev: true + + /arraybuffer.prototype.slice@1.0.1: + resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + define-properties: 1.2.0 + get-intrinsic: 1.2.1 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: true + + /asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + dev: true + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + dependencies: + retry: 0.13.1 + dev: true + + /async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: true + + /aws4@1.12.0: + resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + dev: true + + /axios@1.5.0(debug@4.3.4): + resolution: {integrity: sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==} + dependencies: + follow-redirects: 1.15.2(debug@4.3.4) + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: true + + /bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + dev: true + + /bigint-crypto-utils@3.3.0: + resolution: {integrity: sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==} + engines: {node: '>=14.0.0'} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + dev: true + + /bn.js@4.11.6: + resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} + dev: true + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: true + + /bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: true + + /browser-level@1.0.1: + resolution: {integrity: sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==} + dependencies: + abstract-level: 1.0.3 + catering: 2.1.1 + module-error: 1.0.2 + run-parallel-limit: 1.1.0 + dev: true + + /browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + dev: true + + /browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + dependencies: + base-x: 3.0.9 + dev: true + + /bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + dependencies: + bs58: 4.0.1 + create-hash: 1.2.0 + safe-buffer: 5.2.1 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: true + + /buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + dev: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + dependencies: + streamsearch: 1.1.0 + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /case@1.6.3: + resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: true + + /catering@2.1.1: + resolution: {integrity: sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==} + engines: {node: '>=6'} + dev: true + + /cbor@8.1.0: + resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} + engines: {node: '>=12.19'} + dependencies: + nofilter: 3.1.0 + dev: true + + /cbor@9.0.1: + resolution: {integrity: sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==} + engines: {node: '>=16'} + dependencies: + nofilter: 3.1.0 + dev: true + + /chai-as-promised@7.1.1(chai@4.3.8): + resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} + peerDependencies: + chai: '>= 2.1.2 < 5' + dependencies: + chai: 4.3.8 + check-error: 1.0.2 + dev: true + + /chai@4.3.8: + resolution: {integrity: sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 4.1.3 + get-func-name: 2.0.0 + loupe: 2.3.6 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + dev: true + + /check-error@1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + dev: true + + /chokidar@3.3.0: + resolution: {integrity: sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.2.0 + optionalDependencies: + fsevents: 2.1.3 + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + dev: true + + /cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /classic-level@1.3.0: + resolution: {integrity: sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==} + engines: {node: '>=12'} + requiresBuild: true + dependencies: + abstract-level: 1.0.3 + catering: 2.1.1 + module-error: 1.0.2 + napi-macros: 2.2.2 + node-gyp-build: 4.6.1 + dev: true + + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-table3@0.5.1: + resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} + engines: {node: '>=6'} + dependencies: + object-assign: 4.1.1 + string-width: 2.1.1 + optionalDependencies: + colors: 1.4.0 + dev: true + + /cliui@5.0.0: + resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} + dependencies: + string-width: 3.1.0 + strip-ansi: 5.2.0 + wrap-ansi: 5.1.0 + dev: true + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + dev: true + + /command-line-args@5.2.1: + resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} + engines: {node: '>=4.0.0'} + dependencies: + array-back: 3.1.0 + find-replace: 3.0.0 + lodash.camelcase: 4.3.0 + typical: 4.0.0 + dev: true + + /command-line-usage@6.1.3: + resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} + engines: {node: '>=8.0.0'} + dependencies: + array-back: 4.0.2 + chalk: 2.4.2 + table-layout: 1.0.2 + typical: 5.2.0 + dev: true + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@3.0.2: + resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} + dev: true + + /compare-versions@6.1.0: + resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + dev: true + + /cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + dev: true + + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /cosmiconfig@8.2.0: + resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: true + + /crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + dev: true + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: true + + /create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: true + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + dev: true + + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + + /death@1.1.0: + resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} + dev: true + + /debug@3.2.6(supports-color@6.0.0): + resolution: {integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==} + deprecated: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797) + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + supports-color: 6.0.0 + dev: true + + /debug@4.3.4(supports-color@8.1.1): + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 8.1.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + dev: true + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: true + + /detect-port@1.5.1: + resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} + hasBin: true + dependencies: + address: 1.2.2 + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + dev: true + + /diff@3.5.0: + resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} + engines: {node: '>=0.3.1'} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + dev: true + + /difflib@0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + dependencies: + heap: 0.2.7 + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: true + + /ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: true + + /elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: true + + /emoji-regex@7.0.3: + resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.22.1: + resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.1 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + safe-array-concat: 1.0.0 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.11 + dev: true + + /es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escodegen@1.8.1: + resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} + engines: {node: '>=0.12.0'} + hasBin: true + dependencies: + esprima: 2.7.3 + estraverse: 1.9.3 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.2.0 + dev: true + + /esprima@2.7.3: + resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /estraverse@1.9.3: + resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} + engines: {node: '>=0.10.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eth-gas-reporter@0.2.25: + resolution: {integrity: sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ==} + peerDependencies: + '@codechecks/client': ^0.1.0 + peerDependenciesMeta: + '@codechecks/client': + optional: true + dependencies: + '@ethersproject/abi': 5.7.0 + '@solidity-parser/parser': 0.14.5 + cli-table3: 0.5.1 + colors: 1.4.0 + ethereum-cryptography: 1.2.0 + ethers: 4.0.49 + fs-readdir-recursive: 1.1.0 + lodash: 4.17.21 + markdown-table: 1.1.3 + mocha: 7.2.0 + req-cwd: 2.0.0 + request: 2.88.2 + request-promise-native: 1.0.9(request@2.88.2) + sha1: 1.1.1 + sync-request: 6.1.0 + dev: true + + /ethereum-bloom-filters@1.0.10: + resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} + dependencies: + js-sha3: 0.8.0 + dev: true + + /ethereum-cryptography@0.1.3: + resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + dependencies: + '@types/pbkdf2': 3.1.0 + '@types/secp256k1': 4.0.3 + blakejs: 1.2.1 + browserify-aes: 1.2.0 + bs58check: 2.1.2 + create-hash: 1.2.0 + create-hmac: 1.1.7 + hash.js: 1.1.7 + keccak: 3.0.3 + pbkdf2: 3.1.2 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + scrypt-js: 3.0.1 + secp256k1: 4.0.3 + setimmediate: 1.0.5 + dev: true + + /ethereum-cryptography@1.2.0: + resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} + dependencies: + '@noble/hashes': 1.2.0 + '@noble/secp256k1': 1.7.1 + '@scure/bip32': 1.1.5 + '@scure/bip39': 1.1.1 + dev: true + + /ethereum-cryptography@2.1.2: + resolution: {integrity: sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==} + dependencies: + '@noble/curves': 1.1.0 + '@noble/hashes': 1.3.1 + '@scure/bip32': 1.3.1 + '@scure/bip39': 1.2.1 + dev: true + + /ethereumjs-abi@0.6.8: + resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + dependencies: + bn.js: 4.12.0 + ethereumjs-util: 6.2.1 + dev: true + + /ethereumjs-util@6.2.1: + resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + dependencies: + '@types/bn.js': 4.11.6 + bn.js: 4.12.0 + create-hash: 1.2.0 + elliptic: 6.5.4 + ethereum-cryptography: 0.1.3 + ethjs-util: 0.1.6 + rlp: 2.2.7 + dev: true + + /ethereumjs-util@7.1.5: + resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} + engines: {node: '>=10.0.0'} + dependencies: + '@types/bn.js': 5.1.1 + bn.js: 5.2.1 + create-hash: 1.2.0 + ethereum-cryptography: 0.1.3 + rlp: 2.2.7 + dev: true + + /ethers@4.0.49: + resolution: {integrity: sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==} + dependencies: + aes-js: 3.0.0 + bn.js: 4.12.0 + elliptic: 6.5.4 + hash.js: 1.1.3 + js-sha3: 0.5.7 + scrypt-js: 2.0.4 + setimmediate: 1.0.4 + uuid: 2.0.1 + xmlhttprequest: 1.8.0 + dev: true + + /ethers@5.7.2: + resolution: {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 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /ethers@6.7.1: + resolution: {integrity: sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==} + engines: {node: '>=14.0.0'} + dependencies: + '@adraffy/ens-normalize': 1.9.2 + '@noble/hashes': 1.1.2 + '@noble/secp256k1': 1.7.1 + '@types/node': 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /ethjs-unit@0.1.6: + resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + bn.js: 4.11.6 + number-to-bn: 1.7.0 + dev: true + + /ethjs-util@0.1.6: + resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + is-hex-prefixed: 1.0.0 + strip-hex-prefix: 1.0.0 + dev: true + + /evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: true + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: true + + /fast-base64-decode@1.0.0: + resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-replace@3.0.0: + resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} + engines: {node: '>=4.0.0'} + dependencies: + array-back: 3.1.0 + dev: true + + /find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + dependencies: + locate-path: 2.0.0 + dev: true + + /find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + dependencies: + locate-path: 3.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + dev: true + + /follow-redirects@1.15.2(debug@4.3.4): + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dependencies: + debug: 4.3.4(supports-color@8.1.1) + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: true + + /form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /fp-ts@1.19.3: + resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} + dev: true + + /fs-extra@0.30.0: + resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 2.4.0 + klaw: 1.3.1 + path-is-absolute: 1.0.1 + rimraf: 2.7.1 + dev: true + + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-readdir-recursive@1.1.0: + resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.1.3: + resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + deprecated: '"Please update to latest v2.3 or v2.2"' + requiresBuild: true + dev: true + optional: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + functions-have-names: 1.2.3 + dev: true + + /functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-func-name@2.0.0: + resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + dev: true + + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: true + + /get-port@3.2.0: + resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} + engines: {node: '>=4'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: true + + /ghost-testrpc@0.0.2: + resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} + hasBin: true + dependencies: + chalk: 2.4.2 + node-emoji: 1.11.0 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@5.0.15: + resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} + dependencies: + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.1.3: + resolution: {integrity: sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + + /global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: true + + /global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globby@10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + glob: 7.2.3 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /growl@1.10.5: + resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} + engines: {node: '>=4.x'} + dev: true + + /handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: true + + /har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + dev: true + + /har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + dev: true + + /hardhat-gas-reporter@1.0.9(hardhat@2.17.2): + resolution: {integrity: sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==} + peerDependencies: + hardhat: ^2.0.2 + dependencies: + array-uniq: 1.0.3 + eth-gas-reporter: 0.2.25 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + sha1: 1.1.1 + transitivePeerDependencies: + - '@codechecks/client' + dev: true + + /hardhat@2.17.2(ts-node@10.9.1)(typescript@5.2.2): + resolution: {integrity: sha512-oUv40jBeHw0dKpbyQ+iH9cmNMziweLoTW3MnkNxJ2Gc0KGLrQR/1n4vV4xY60zn2LdmRgnwPqy3CgtY0mfwIIA==} + hasBin: true + peerDependencies: + ts-node: '*' + typescript: '*' + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + dependencies: + '@ethersproject/abi': 5.7.0 + '@metamask/eth-sig-util': 4.0.1 + '@nomicfoundation/ethereumjs-block': 5.0.2 + '@nomicfoundation/ethereumjs-blockchain': 7.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.2 + '@nomicfoundation/ethereumjs-evm': 2.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-statemanager': 2.0.2 + '@nomicfoundation/ethereumjs-trie': 6.0.2 + '@nomicfoundation/ethereumjs-tx': 5.0.2 + '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.2 + '@nomicfoundation/solidity-analyzer': 0.1.1 + '@sentry/node': 5.30.0 + '@types/bn.js': 5.1.1 + '@types/lru-cache': 5.1.1 + adm-zip: 0.4.16 + aggregate-error: 3.1.0 + ansi-escapes: 4.3.2 + chalk: 2.4.2 + chokidar: 3.5.3 + ci-info: 2.0.0 + debug: 4.3.4(supports-color@8.1.1) + enquirer: 2.4.1 + env-paths: 2.2.1 + ethereum-cryptography: 1.2.0 + ethereumjs-abi: 0.6.8 + find-up: 2.1.0 + fp-ts: 1.19.3 + fs-extra: 7.0.1 + glob: 7.2.0 + immutable: 4.3.4 + io-ts: 1.10.4 + keccak: 3.0.3 + lodash: 4.17.21 + mnemonist: 0.38.5 + mocha: 10.2.0 + p-map: 4.0.0 + raw-body: 2.5.2 + resolve: 1.17.0 + semver: 6.3.1 + solc: 0.7.3(debug@4.3.4) + source-map-support: 0.5.21 + stacktrace-parser: 0.1.10 + ts-node: 10.9.1(@types/node@20.5.7)(typescript@5.2.2) + tsort: 0.0.1 + typescript: 5.2.2 + undici: 5.23.0 + uuid: 8.3.2 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: true + + /hash.js@1.1.3: + resolution: {integrity: sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: true + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: true + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + dev: true + + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: true + + /http-basic@8.1.3: + resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} + engines: {node: '>=6.0.0'} + dependencies: + caseless: 0.12.0 + concat-stream: 1.6.2 + http-response-object: 3.0.2 + parse-cache-control: 1.0.1 + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: true + + /http-response-object@3.0.2: + resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} + dependencies: + '@types/node': 10.17.60 + dev: true + + /http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.17.0 + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + dev: true + + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true + + /io-ts@1.10.4: + resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + dependencies: + fp-ts: 1.19.3 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-hex-prefixed@1.0.0: + resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} + engines: {node: '>=6.5.0', npm: '>=3'} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + dependencies: + node-fetch: 2.7.0 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + dev: true + + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: true + + /js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + dev: true + + /js-sdsl@4.4.2: + resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} + dev: true + + /js-sha3@0.5.7: + resolution: {integrity: sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==} + dev: true + + /js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@3.13.1: + resolution: {integrity: sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /jsonfile@2.4.0: + resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonschema@1.4.1: + resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + dev: true + + /jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: true + + /keccak@3.0.3: + resolution: {integrity: sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==} + engines: {node: '>=10.0.0'} + requiresBuild: true + dependencies: + node-addon-api: 2.0.2 + node-gyp-build: 4.6.1 + readable-stream: 3.6.2 + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /klaw@1.3.1: + resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /level-supports@4.0.1: + resolution: {integrity: sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==} + engines: {node: '>=12'} + dev: true + + /level-transcoder@1.0.1: + resolution: {integrity: sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==} + engines: {node: '>=12'} + dependencies: + buffer: 6.0.3 + module-error: 1.0.2 + dev: true + + /level@8.0.0: + resolution: {integrity: sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==} + engines: {node: '>=12'} + dependencies: + browser-level: 1.0.1 + classic-level: 1.3.0 + dev: true + + /levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + dev: true + + /locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + + /lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + dev: true + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: true + + /lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@3.0.0: + resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} + engines: {node: '>=8'} + dependencies: + chalk: 2.4.2 + dev: true + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /loupe@2.3.6: + resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + dependencies: + get-func-name: 2.0.0 + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lru_map@0.3.3: + resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + dev: true + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /markdown-table@1.1.3: + resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} + dev: true + + /mcl-wasm@0.7.9: + resolution: {integrity: sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==} + engines: {node: '>=8.9.0'} + dev: true + + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /memory-level@1.0.0: + resolution: {integrity: sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==} + engines: {node: '>=12'} + dependencies: + abstract-level: 1.0.3 + functional-red-black-tree: 1.0.1 + module-error: 1.0.2 + dev: true + + /memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micro-ftch@0.3.1: + resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: true + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /mkdirp@0.5.5: + resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mnemonist@0.38.5: + resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + dependencies: + obliterator: 2.0.4 + dev: true + + /mocha@10.2.0: + resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} + engines: {node: '>= 14.0.0'} + hasBin: true + dependencies: + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.4(supports-color@8.1.1) + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 7.2.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.0.1 + ms: 2.1.3 + nanoid: 3.3.3 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.2.1 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + dev: true + + /mocha@7.1.2: + resolution: {integrity: sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==} + engines: {node: '>= 8.10.0'} + hasBin: true + dependencies: + ansi-colors: 3.2.3 + browser-stdout: 1.3.1 + chokidar: 3.3.0 + debug: 3.2.6(supports-color@6.0.0) + diff: 3.5.0 + escape-string-regexp: 1.0.5 + find-up: 3.0.0 + glob: 7.1.3 + growl: 1.10.5 + he: 1.2.0 + js-yaml: 3.13.1 + log-symbols: 3.0.0 + minimatch: 5.1.6 + mkdirp: 0.5.5 + ms: 2.1.1 + node-environment-flags: 1.0.6 + object.assign: 4.1.0 + strip-json-comments: 2.0.1 + supports-color: 6.0.0 + which: 1.3.1 + wide-align: 1.1.3 + yargs: 13.3.2 + yargs-parser: 13.1.2 + yargs-unparser: 1.6.0 + dev: true + + /mocha@7.2.0: + resolution: {integrity: sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==} + engines: {node: '>= 8.10.0'} + hasBin: true + dependencies: + ansi-colors: 3.2.3 + browser-stdout: 1.3.1 + chokidar: 3.3.0 + debug: 3.2.6(supports-color@6.0.0) + diff: 3.5.0 + escape-string-regexp: 1.0.5 + find-up: 3.0.0 + glob: 7.1.3 + growl: 1.10.5 + he: 1.2.0 + js-yaml: 3.13.1 + log-symbols: 3.0.0 + minimatch: 5.1.6 + mkdirp: 0.5.5 + ms: 2.1.1 + node-environment-flags: 1.0.6 + object.assign: 4.1.0 + strip-json-comments: 2.0.1 + supports-color: 6.0.0 + which: 1.3.1 + wide-align: 1.1.3 + yargs: 13.3.2 + yargs-parser: 13.1.2 + yargs-unparser: 1.6.0 + dev: true + + /module-error@1.0.2: + resolution: {integrity: sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==} + engines: {node: '>=10'} + dev: true + + /ms@2.1.1: + resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /nanoid@3.3.3: + resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /napi-macros@2.2.2: + resolution: {integrity: sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + dev: true + + /node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + dependencies: + lodash: 4.17.21 + dev: true + + /node-environment-flags@1.0.6: + resolution: {integrity: sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==} + dependencies: + object.getownpropertydescriptors: 2.1.6 + semver: 5.7.2 + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-gyp-build@4.6.1: + resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==} + hasBin: true + dev: true + + /nofilter@3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + dev: true + + /nopt@3.0.6: + resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} + hasBin: true + dependencies: + abbrev: 1.0.9 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /number-to-bn@1.7.0: + resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + bn.js: 4.11.6 + strip-hex-prefix: 1.0.0 + dev: true + + /oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.0: + resolution: {integrity: sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + function-bind: 1.1.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.getownpropertydescriptors@2.1.6: + resolution: {integrity: sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==} + engines: {node: '>= 0.8'} + dependencies: + array.prototype.reduce: 1.0.6 + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + safe-array-concat: 1.0.0 + dev: true + + /obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.5 + dev: true + + /ordinal@1.0.3: + resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-limit@1.3.0: + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} + dependencies: + p-try: 1.0.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + dependencies: + p-limit: 1.3.0 + dev: true + + /p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-try@1.0.0: + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-cache-control@1.0.1: + resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: true + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: true + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier-plugin-solidity@1.1.3(prettier@2.8.8): + resolution: {integrity: sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==} + engines: {node: '>=12'} + peerDependencies: + prettier: '>=2.3.0 || >=3.0.0-alpha.0' + dependencies: + '@solidity-parser/parser': 0.16.1 + prettier: 2.8.8 + semver: 7.5.4 + solidity-comments-extractor: 0.0.7 + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + requiresBuild: true + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + dependencies: + asap: 2.0.6 + dev: true + + /proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: true + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + + /qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + dev: true + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.2.0: + resolution: {integrity: sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==} + engines: {node: '>= 8'} + dependencies: + picomatch: 2.3.1 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.22.4 + dev: true + + /recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + dependencies: + minimatch: 3.1.2 + dev: true + + /reduce-flatten@2.0.0: + resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} + engines: {node: '>=6'} + dev: true + + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /req-cwd@2.0.0: + resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} + engines: {node: '>=4'} + dependencies: + req-from: 2.0.0 + dev: true + + /req-from@2.0.0: + resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} + engines: {node: '>=4'} + dependencies: + resolve-from: 3.0.0 + dev: true + + /request-promise-core@1.1.4(request@2.88.2): + resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + dependencies: + lodash: 4.17.21 + request: 2.88.2 + dev: true + + /request-promise-native@1.0.9(request@2.88.2): + resolution: {integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==} + engines: {node: '>=0.12.0'} + deprecated: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + dependencies: + request: 2.88.2 + request-promise-core: 1.1.4(request@2.88.2) + stealthy-require: 1.1.1 + tough-cookie: 4.1.3 + dev: true + + /request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.12.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 4.1.3 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-from@3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.1.7: + resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} + dev: true + + /resolve@1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + dependencies: + path-parse: 1.0.7 + dev: true + + /resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + dev: true + + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.0 + dev: true + + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: true + + /rlp@2.2.7: + resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} + hasBin: true + dependencies: + bn.js: 5.2.1 + dev: true + + /run-parallel-limit@1.1.0: + resolution: {integrity: sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rustbn.js@0.2.0: + resolution: {integrity: sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==} + dev: true + + /safe-array-concat@1.0.0: + resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /sc-istanbul@0.4.6: + resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} + hasBin: true + dependencies: + abbrev: 1.0.9 + async: 1.5.2 + escodegen: 1.8.1 + esprima: 2.7.3 + glob: 5.0.15 + handlebars: 4.7.8 + js-yaml: 3.14.1 + mkdirp: 0.5.6 + nopt: 3.0.6 + once: 1.4.0 + resolve: 1.1.7 + supports-color: 3.2.3 + which: 1.3.1 + wordwrap: 1.0.0 + dev: true + + /scrypt-js@2.0.4: + resolution: {integrity: sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==} + dev: true + + /scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + dev: true + + /secp256k1@4.0.3: + resolution: {integrity: sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==} + engines: {node: '>=10.0.0'} + requiresBuild: true + dependencies: + elliptic: 6.5.4 + node-addon-api: 2.0.2 + node-gyp-build: 4.6.1 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + dependencies: + randombytes: 2.1.0 + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /setimmediate@1.0.4: + resolution: {integrity: sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==} + dev: true + + /setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: true + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: true + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /sha1@1.1.1: + resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + dev: true + + /shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /solc@0.7.3(debug@4.3.4): + resolution: {integrity: sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + command-exists: 1.2.9 + commander: 3.0.2 + follow-redirects: 1.15.2(debug@4.3.4) + fs-extra: 0.30.0 + js-sha3: 0.8.0 + memorystream: 0.3.1 + require-from-string: 2.0.2 + semver: 5.7.2 + tmp: 0.0.33 + transitivePeerDependencies: + - debug + dev: true + + /solhint-plugin-prettier@0.0.5(prettier-plugin-solidity@1.1.3)(prettier@2.8.8): + resolution: {integrity: sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==} + peerDependencies: + prettier: ^1.15.0 || ^2.0.0 + prettier-plugin-solidity: ^1.0.0-alpha.14 + dependencies: + prettier: 2.8.8 + prettier-linter-helpers: 1.0.0 + prettier-plugin-solidity: 1.1.3(prettier@2.8.8) + dev: true + + /solhint@3.6.2: + resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} + hasBin: true + dependencies: + '@solidity-parser/parser': 0.16.1 + ajv: 6.12.6 + antlr4: 4.13.0 + ast-parents: 0.0.1 + chalk: 4.1.2 + commander: 10.0.1 + cosmiconfig: 8.2.0 + fast-diff: 1.3.0 + glob: 8.1.0 + ignore: 5.2.4 + js-yaml: 4.1.0 + lodash: 4.17.21 + pluralize: 8.0.0 + semver: 7.5.4 + strip-ansi: 6.0.1 + table: 6.8.1 + text-table: 0.2.0 + optionalDependencies: + prettier: 2.8.8 + dev: true + + /solidity-ast@0.4.52: + resolution: {integrity: sha512-iOya9BSiB9jhM8Vf40n8lGELGzwrUc57rl5BhfNtJ5cvAaMvRcNlHeAMNvqJJyjoUnczqRbHqdivEqK89du3Cw==} + dependencies: + array.prototype.findlast: 1.2.3 + dev: true + + /solidity-comments-extractor@0.0.7: + resolution: {integrity: sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==} + dev: true + + /solidity-coverage@0.8.4(hardhat@2.17.2): + resolution: {integrity: sha512-xeHOfBOjdMF6hWTbt42iH4x+7j1Atmrf5OldDPMxI+i/COdExUxszOswD9qqvcBTaLGiOrrpnh9UZjSpt4rBsg==} + hasBin: true + peerDependencies: + hardhat: ^2.11.0 + dependencies: + '@ethersproject/abi': 5.7.0 + '@solidity-parser/parser': 0.16.1 + chalk: 2.4.2 + death: 1.1.0 + detect-port: 1.5.1 + difflib: 0.2.4 + fs-extra: 8.1.0 + ghost-testrpc: 0.0.2 + global-modules: 2.0.0 + globby: 10.0.2 + hardhat: 2.17.2(ts-node@10.9.1)(typescript@5.2.2) + jsonschema: 1.4.1 + lodash: 4.17.21 + mocha: 7.1.2 + node-emoji: 1.11.0 + pify: 4.0.1 + recursive-readdir: 2.2.3 + sc-istanbul: 0.4.6 + semver: 7.5.4 + shelljs: 0.8.5 + web3-utils: 1.10.2 + transitivePeerDependencies: + - supports-color + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.2.0: + resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} + engines: {node: '>=0.8.0'} + requiresBuild: true + dependencies: + amdefine: 1.0.1 + dev: true + optional: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /sshpk@1.17.0: + resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: true + + /stacktrace-parser@0.1.10: + resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} + engines: {node: '>=6'} + dependencies: + type-fest: 0.7.1 + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: true + + /stealthy-require@1.1.1: + resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} + engines: {node: '>=0.10.0'} + dev: true + + /streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + dev: true + + /string-format@2.0.0: + resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} + dev: true + + /string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: true + + /string-width@3.1.0: + resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} + engines: {node: '>=6'} + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + dependencies: + ansi-regex: 3.0.1 + dev: true + + /strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + dependencies: + ansi-regex: 4.1.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-hex-prefix@1.0.0: + resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + is-hex-prefixed: 1.0.0 + dev: true + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + dependencies: + has-flag: 1.0.0 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@6.0.0: + resolution: {integrity: sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==} + engines: {node: '>=6'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /sync-request@6.1.0: + resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} + engines: {node: '>=8.0.0'} + dependencies: + http-response-object: 3.0.2 + sync-rpc: 1.3.6 + then-request: 6.0.2 + dev: true + + /sync-rpc@1.3.6: + resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} + dependencies: + get-port: 3.2.0 + dev: true + + /table-layout@1.0.2: + resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} + engines: {node: '>=8.0.0'} + dependencies: + array-back: 4.0.2 + deep-extend: 0.6.0 + typical: 5.2.0 + wordwrapjs: 4.0.1 + dev: true + + /table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.12.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /then-request@6.0.2: + resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} + engines: {node: '>=6.0.0'} + dependencies: + '@types/concat-stream': 1.6.1 + '@types/form-data': 0.0.33 + '@types/node': 8.10.66 + '@types/qs': 6.9.8 + caseless: 0.12.0 + concat-stream: 1.6.2 + form-data: 2.5.1 + http-basic: 8.1.3 + http-response-object: 3.0.2 + promise: 8.3.0 + qs: 6.11.2 + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: true + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /ts-command-line-args@2.5.1: + resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} + hasBin: true + dependencies: + chalk: 4.1.2 + command-line-args: 5.2.1 + command-line-usage: 6.1.3 + string-format: 2.0.0 + dev: true + + /ts-essentials@7.0.3(typescript@5.2.2): + resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} + peerDependencies: + typescript: '>=3.7.0' + dependencies: + typescript: 5.2.2 + dev: true + + /ts-node@10.9.1(@types/node@20.5.7)(typescript@5.2.2): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.5.7 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.2.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /tsort@0.0.1: + resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} + dev: true + + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + dev: true + + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: true + + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: true + + /type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + dev: true + + /typechain@8.3.1(typescript@5.2.2): + resolution: {integrity: sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==} + hasBin: true + peerDependencies: + typescript: '>=4.3.0' + dependencies: + '@types/prettier': 2.7.3 + debug: 4.3.4(supports-color@8.1.1) + fs-extra: 7.0.1 + glob: 7.1.7 + js-sha3: 0.8.0 + lodash: 4.17.21 + mkdirp: 1.0.4 + prettier: 2.8.8 + ts-command-line-args: 2.5.1 + ts-essentials: 7.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + dev: true + + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /typical@4.0.0: + resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} + engines: {node: '>=8'} + dev: true + + /typical@5.2.0: + resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} + engines: {node: '>=8'} + dev: true + + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici@5.23.0: + resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==} + engines: {node: '>=14.0'} + dependencies: + busboy: 1.6.0 + dev: true + + /unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} + dev: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + + /utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /uuid@2.0.1: + resolution: {integrity: sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + dev: true + + /uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: true + + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + + /web3-utils@1.10.2: + resolution: {integrity: sha512-TdApdzdse5YR+5GCX/b/vQnhhbj1KSAtfrDtRW7YS0kcWp1gkJsN62gw6GzCaNTeXookB7UrLtmDUuMv65qgow==} + engines: {node: '>=8.0.0'} + dependencies: + '@ethereumjs/util': 8.1.0 + bn.js: 5.2.1 + ethereum-bloom-filters: 1.0.10 + ethereum-cryptography: 2.1.2 + ethjs-unit: 0.1.6 + number-to-bn: 1.7.0 + randombytes: 2.1.0 + utf8: 3.0.0 + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: true + + /which-typed-array@1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wide-align@1.1.3: + resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==} + dependencies: + string-width: 2.1.1 + dev: true + + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + + /wordwrapjs@4.0.1: + resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} + engines: {node: '>=8.0.0'} + dependencies: + reduce-flatten: 2.0.0 + typical: 5.2.0 + dev: true + + /workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + dev: true + + /wrap-ansi@5.1.0: + resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} + engines: {node: '>=6'} + dependencies: + ansi-styles: 3.2.1 + string-width: 3.1.0 + strip-ansi: 5.2.0 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xmlhttprequest@1.8.0: + resolution: {integrity: sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==} + engines: {node: '>=0.4.0'} + dev: true + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser@13.1.2: + resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + dev: true + + /yargs-unparser@1.6.0: + resolution: {integrity: sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==} + engines: {node: '>=6'} + dependencies: + flat: 5.0.2 + lodash: 4.17.21 + yargs: 13.3.2 + dev: true + + /yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + dev: true + + /yargs@13.3.2: + resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} + dependencies: + cliui: 5.0.0 + find-up: 3.0.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 3.1.0 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 13.1.2 + dev: true + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.4 + dev: true + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/release.sh b/release.sh new file mode 100755 index 00000000..97f5c641 --- /dev/null +++ b/release.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +git config user.name github-actions[bot] +git config user.email github-actions[bot]@users.noreply.github.com + +git checkout main + +git merge --no-edit --no-ff dev +git push origin main + +git checkout dev +git rebase main +git push origin dev diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..76f932e9 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,5 @@ +ds-test/=lib/forge-std/lib/ds-test/src/ +erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ +forge-std/=lib/forge-std/src/ +openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/ +openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/ diff --git a/script/checkUpgradeability.ts b/script/checkUpgradeability.ts new file mode 100644 index 00000000..cbe56b14 --- /dev/null +++ b/script/checkUpgradeability.ts @@ -0,0 +1,34 @@ +import { ethers, upgrades } from "hardhat"; + +async function main() { + console.log("Checking contracts for upgradeability..."); + + console.log("Checking AttestationRegistry..."); + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + await upgrades.validateImplementation(AttestationRegistry); + console.log("AttestationRegistry OK"); + + console.log("Checking ModuleRegistry..."); + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + await upgrades.validateImplementation(ModuleRegistry); + console.log("ModuleRegistry OK"); + + console.log("Checking PortalRegistry..."); + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + await upgrades.validateImplementation(PortalRegistry); + console.log("PortalRegistry OK"); + + console.log("Checking SchemaRegistry..."); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + await upgrades.validateImplementation(SchemaRegistry); + console.log("SchemaRegistry OK"); + + console.log("All contracts are upgradeable!"); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/deploy/deployCorrectModule.ts b/script/deploy/deployCorrectModule.ts new file mode 100644 index 00000000..4e51069a --- /dev/null +++ b/script/deploy/deployCorrectModule.ts @@ -0,0 +1,22 @@ +import { ethers, run } from "hardhat"; + +async function main() { + console.log("Deploying CorrectModule..."); + const CorrectModule = await ethers.getContractFactory("CorrectModule"); + const correctModule = await CorrectModule.deploy(); + await correctModule.waitForDeployment(); + const correctModuleAddress = await correctModule.getAddress(); + + await run("verify:verify", { + address: correctModuleAddress, + }); + + console.log(`CorrectModule successfully deployed and verified at ${correctModuleAddress}!`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/deploy/deployEverything.ts b/script/deploy/deployEverything.ts new file mode 100644 index 00000000..e7bdb2ce --- /dev/null +++ b/script/deploy/deployEverything.ts @@ -0,0 +1,145 @@ +import { ethers, run, upgrades } from "hardhat"; + +async function main() { + console.log(`START SCRIPT`); + + console.log("Deploying Router..."); + const Router = await ethers.getContractFactory("Router"); + const router = await upgrades.deployProxy(Router); + await router.waitForDeployment(); + const routerProxyAddress = await router.getAddress(); + const routerImplementationAddress = await upgrades.erc1967.getImplementationAddress(routerProxyAddress); + + await run("verify:verify", { + address: routerProxyAddress, + }); + + console.log(`Router successfully deployed and verified!`); + console.log(`Proxy is at ${routerProxyAddress}`); + console.log(`Implementation is at ${routerImplementationAddress}`); + + console.log(`\n----\n`); + + console.log("Deploying AttestationRegistry..."); + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + const attestationRegistry = await upgrades.deployProxy(AttestationRegistry); + await attestationRegistry.waitForDeployment(); + const attestationRegistryProxyAddress = await attestationRegistry.getAddress(); + const attestationRegistryImplementationAddress = await upgrades.erc1967.getImplementationAddress( + attestationRegistryProxyAddress, + ); + + await run("verify:verify", { + address: attestationRegistryProxyAddress, + }); + + console.log(`AttestationRegistry successfully deployed and verified!`); + console.log(`Proxy is at ${attestationRegistryProxyAddress}`); + console.log(`Implementation is at ${attestationRegistryImplementationAddress}`); + + console.log(`\n----\n`); + + console.log("Deploying ModuleRegistry..."); + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + const moduleRegistry = await upgrades.deployProxy(ModuleRegistry); + await moduleRegistry.waitForDeployment(); + const moduleRegistryProxyAddress = await moduleRegistry.getAddress(); + const moduleRegistryImplementationAddress = await upgrades.erc1967.getImplementationAddress( + moduleRegistryProxyAddress, + ); + + await run("verify:verify", { + address: moduleRegistryProxyAddress, + }); + + console.log(`ModuleRegistry successfully deployed and verified!`); + console.log(`Proxy is at ${moduleRegistryProxyAddress}`); + console.log(`Implementation is at ${moduleRegistryImplementationAddress}`); + + console.log(`\n----\n`); + + console.log("Deploying PortalRegistry..."); + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + const portalRegistry = await upgrades.deployProxy(PortalRegistry); + await portalRegistry.waitForDeployment(); + const portalRegistryProxyAddress = await portalRegistry.getAddress(); + const portalRegistryImplementationAddress = await upgrades.erc1967.getImplementationAddress( + portalRegistryProxyAddress, + ); + + await run("verify:verify", { + address: portalRegistryProxyAddress, + }); + + console.log(`PortalRegistry successfully deployed and verified!`); + console.log(`Proxy is at ${portalRegistryProxyAddress}`); + console.log(`Implementation is at ${portalRegistryImplementationAddress}`); + + console.log(`\n----\n`); + + console.log("Deploying SchemaRegistry..."); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + const schemaRegistry = await upgrades.deployProxy(SchemaRegistry); + await schemaRegistry.waitForDeployment(); + const schemaRegistryProxyAddress = await schemaRegistry.getAddress(); + const schemaRegistryImplementationAddress = await upgrades.erc1967.getImplementationAddress( + schemaRegistryProxyAddress, + ); + + await run("verify:verify", { + address: schemaRegistryProxyAddress, + }); + + console.log(`SchemaRegistry successfully deployed and verified!`); + console.log(`Proxy is at ${schemaRegistryProxyAddress}`); + console.log(`Implementation is at ${schemaRegistryImplementationAddress}`); + + console.log(`\n----\n`); + + console.log("Updating Router with the registries addresses..."); + await router.updateAttestationRegistry(attestationRegistryProxyAddress); + await router.updateModuleRegistry(moduleRegistryProxyAddress); + await router.updatePortalRegistry(portalRegistryProxyAddress); + await router.updateSchemaRegistry(schemaRegistryProxyAddress); + console.log("Router updated with the registries addresses!"); + + console.log(`\n----\n`); + + console.log(`Updating registries with the Router address...`); + + console.log("Updating AttestationRegistry with the Router address..."); + await attestationRegistry.updateRouter(routerProxyAddress); + console.log("AttestationRegistry updated!"); + + console.log("Updating ModuleRegistry with the Router address..."); + await moduleRegistry.updateRouter(routerProxyAddress); + console.log("ModuleRegistry updated!"); + + console.log("Updating PortalRegistry with the Router address..."); + await portalRegistry.updateRouter(routerProxyAddress); + console.log("PortalRegistry updated!"); + + console.log("Updating SchemaRegistry with the Router address..."); + await schemaRegistry.updateRouter(routerProxyAddress); + console.log("SchemaRegistry updated!"); + + console.log("Registries updated with the Router address!"); + + console.log(`\n----\n`); + + console.log(`** SUMMARY **`); + console.log(`Router = ${routerProxyAddress}`); + console.log(`AttestationRegistry = ${attestationRegistryProxyAddress}`); + console.log(`ModuleRegistry = ${moduleRegistryProxyAddress}`); + console.log(`PortalRegistry = ${portalRegistryProxyAddress}`); + console.log(`SchemaRegistry = ${schemaRegistryProxyAddress}`); + + console.log(`END SCRIPT`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/deploy/deployIncorrectModule.ts b/script/deploy/deployIncorrectModule.ts new file mode 100644 index 00000000..7f615139 --- /dev/null +++ b/script/deploy/deployIncorrectModule.ts @@ -0,0 +1,22 @@ +import { ethers, run } from "hardhat"; + +async function main() { + console.log("Deploying IncorrectModule..."); + const IncorrectModule = await ethers.getContractFactory("IncorrectModule"); + const incorrectModule = await IncorrectModule.deploy(); + await incorrectModule.waitForDeployment(); + const incorrectModuleAddress = await incorrectModule.getAddress(); + + await run("verify:verify", { + address: incorrectModuleAddress, + }); + + console.log(`IncorrectModule successfully deployed and verified at ${incorrectModuleAddress}!`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/deploy/deployMsgSenderModule.ts b/script/deploy/deployMsgSenderModule.ts new file mode 100644 index 00000000..58010533 --- /dev/null +++ b/script/deploy/deployMsgSenderModule.ts @@ -0,0 +1,22 @@ +import { ethers, run } from "hardhat"; + +async function main() { + console.log("Deploying MsgSenderModule..."); + const MsgSenderModule = await ethers.getContractFactory("MsgSenderModule"); + const msgSenderModule = await MsgSenderModule.deploy(); + await msgSenderModule.waitForDeployment(); + const msgSenderModuleAddress = await msgSenderModule.getAddress(); + + await run("verify:verify", { + address: msgSenderModuleAddress, + }); + + console.log(`MsgSenderModule successfully deployed and verified at ${msgSenderModuleAddress}!`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/deploy/postDeployment.ts b/script/deploy/postDeployment.ts new file mode 100644 index 00000000..61d138d6 --- /dev/null +++ b/script/deploy/postDeployment.ts @@ -0,0 +1,48 @@ +import { ethers } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + console.log("Creating relationship schema using schema registry, with proxy at", proxyAddress); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + const schemaRegistry = SchemaRegistry.attach(proxyAddress); + await createSchema(schemaRegistry, + "Relationship", + "Creates a named relationship between two attestations", + "https://schema.org/Property", + "bytes32 subject, string predicate, bytes32 object"); + await createSchema(schemaRegistry, + "namedGraphRelationship", + "Creates a named relationship between two attestations inside a specific named graph", + "https://schema.org/Property", + "string namedGraph, bytes32 subject, string predicate, bytes32 object"); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + +async function createSchema(schemaRegistry, schemaName, schemaDescription, schemaContext, schemaString) { + const schemaId = await schemaRegistry.getIdFromSchemaString(schemaString); + const schemaExists = await schemaRegistry.isRegistered(schemaId); + if (!schemaExists) { + const tx = await schemaRegistry.createSchema(schemaName, schemaDescription, schemaContext, schemaString); + await tx.wait(); + const schemaCreated = await schemaRegistry.isRegistered(schemaId); + if (schemaCreated) + console.log(`${schemaName} schema creation succeeded, schema id : ${schemaId}`); + + else + console.log(`${schemaName} schema creation failed, schema id : ${schemaId}`); + } + + else { + console.log(`${schemaName} schema already exists, schema id : ${schemaId}`); + } +} + diff --git a/script/upgrade/upgradeAttestationRegistry.ts b/script/upgrade/upgradeAttestationRegistry.ts new file mode 100644 index 00000000..c21b4001 --- /dev/null +++ b/script/upgrade/upgradeAttestationRegistry.ts @@ -0,0 +1,30 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; + console.log("Upgrading AttestationRegistry, with proxy at", proxyAddress); + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + const attestationRegistry = await upgrades.upgradeProxy(proxyAddress, AttestationRegistry); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); + + await run("verify:verify", { + address: proxyAddress, + }); + + await attestationRegistry.incrementVersionNumber(); + const newVersion = await attestationRegistry.getVersionNumber(); + + console.log(`AttestationRegistry successfully upgraded to version ${newVersion} and verified!`); + console.log(`Proxy is at ${proxyAddress}`); + console.log(`Implementation is at ${implementationAddress}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradeModuleRegistry.ts b/script/upgrade/upgradeModuleRegistry.ts new file mode 100644 index 00000000..9b066197 --- /dev/null +++ b/script/upgrade/upgradeModuleRegistry.ts @@ -0,0 +1,27 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; + console.log("Upgrading ModuleRegistry, with proxy at", proxyAddress); + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + await upgrades.upgradeProxy(proxyAddress, ModuleRegistry); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); + + await run("verify:verify", { + address: proxyAddress, + }); + + console.log(`ModuleRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${proxyAddress}`); + console.log(`Implementation is at ${implementationAddress}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradePortalRegistry.ts b/script/upgrade/upgradePortalRegistry.ts new file mode 100644 index 00000000..7a0873f4 --- /dev/null +++ b/script/upgrade/upgradePortalRegistry.ts @@ -0,0 +1,27 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; + console.log("Upgrading PortalRegistry, with proxy at", proxyAddress); + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + await upgrades.upgradeProxy(proxyAddress, PortalRegistry); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); + + await run("verify:verify", { + address: proxyAddress, + }); + + console.log(`PortalRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${proxyAddress}`); + console.log(`Implementation is at ${implementationAddress}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradeRouter.ts b/script/upgrade/upgradeRouter.ts new file mode 100644 index 00000000..dab75a40 --- /dev/null +++ b/script/upgrade/upgradeRouter.ts @@ -0,0 +1,27 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.ROUTER_ADDRESS ?? ""; + console.log("Upgrading Router, with proxy at", proxyAddress); + const Router = await ethers.getContractFactory("Router"); + await upgrades.upgradeProxy(proxyAddress, Router); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); + + await run("verify:verify", { + address: proxyAddress, + }); + + console.log(`Router successfully upgraded and verified!`); + console.log(`Proxy is at ${proxyAddress}`); + console.log(`Implementation is at ${implementationAddress}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradeSchemaRegistry.ts b/script/upgrade/upgradeSchemaRegistry.ts new file mode 100644 index 00000000..47ea6677 --- /dev/null +++ b/script/upgrade/upgradeSchemaRegistry.ts @@ -0,0 +1,27 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + const proxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + console.log("Upgrading SchemaRegistry, with proxy at", proxyAddress); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + await upgrades.upgradeProxy(proxyAddress, SchemaRegistry); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); + + await run("verify:verify", { + address: proxyAddress, + }); + + console.log(`SchemaRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${proxyAddress}`); + console.log(`Implementation is at ${implementationAddress}`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/src/AttestationRegistry.sol b/src/AttestationRegistry.sol new file mode 100644 index 00000000..795a4774 --- /dev/null +++ b/src/AttestationRegistry.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import { Attestation, AttestationPayload } from "./types/Structs.sol"; +import { PortalRegistry } from "./PortalRegistry.sol"; +import { SchemaRegistry } from "./SchemaRegistry.sol"; +import { IRouter } from "./interface/IRouter.sol"; + +/** + * @title Attestation Registry + * @author Consensys + * @notice This contract stores a registry of all attestations + */ +contract AttestationRegistry is OwnableUpgradeable { + IRouter public router; + + uint16 private version; + uint32 private attestationIdCounter; + + mapping(bytes32 attestationId => Attestation attestation) private attestations; + + /// @notice Error thrown when a non-portal tries to call a method that can only be called by a portal + error OnlyPortal(); + /// @notice Error thrown when an invalid Router address is given + error RouterInvalid(); + /// @notice Error thrown when an attestation is not registered in the AttestationRegistry + error AttestationNotAttested(); + /// @notice Error thrown when an attempt is made to revoke an attestation by an entity other than the attesting portal + error OnlyAttestingPortal(); + /// @notice Error thrown when a schema id is not registered + error SchemaNotRegistered(); + /// @notice Error thrown when an attestation subject is empty + error AttestationSubjectFieldEmpty(); + /// @notice Error thrown when an attestation data field is empty + error AttestationDataFieldEmpty(); + /// @notice Error thrown when an attempt is made to revoke an attestation that was already revoked + error AlreadyRevoked(); + /// @notice Error thrown when an attempt is made to revoke an attestation based on a non-revocable schema + error AttestationNotRevocable(); + /// @notice Error thrown when attempting to bulk revoke attestations without the same number of replacing attestations + error BulkRevocationInvalidParams(); + + /// @notice Event emitted when an attestation is registered + event AttestationRegistered(bytes32 indexed attestationId); + /// @notice Event emitted when an attestation is revoked + event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + /// @notice Event emitted when the version number is incremented + event VersionUpdated(uint16 version); + + /** + * @notice Checks if the caller is a registered portal + * @param portal the portal address + */ + modifier onlyPortals(address portal) { + bool isPortalRegistered = PortalRegistry(router.getPortalRegistry()).isRegistered(portal); + if (!isPortalRegistered) revert OnlyPortal(); + _; + } + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /** + * @notice Contract initialization + */ + function initialize() public initializer { + __Ownable_init(); + } + + /** + * @notice Changes the address for the Router + */ + function updateRouter(address _router) public onlyOwner { + if (_router == address(0)) revert RouterInvalid(); + router = IRouter(_router); + } + + /** + * @notice Registers an attestation to the AttestationRegistry + * @param attestationPayload the attestation payload to create attestation and register it + * @param attester the account address issuing the attestation + * @dev This method is only callable by a registered Portal + */ + function attest(AttestationPayload calldata attestationPayload, address attester) public onlyPortals(msg.sender) { + // Verify the schema id exists + SchemaRegistry schemaRegistry = SchemaRegistry(router.getSchemaRegistry()); + if (!schemaRegistry.isRegistered(attestationPayload.schemaId)) revert SchemaNotRegistered(); + // Verify the subject field is not blank + if (attestationPayload.subject.length == 0) revert AttestationSubjectFieldEmpty(); + // Verify the attestationData field is not blank + if (attestationPayload.attestationData.length == 0) revert AttestationDataFieldEmpty(); + // Auto increment attestation counter + attestationIdCounter++; + // Create attestation + Attestation memory attestation = Attestation( + bytes32(abi.encode(attestationIdCounter)), + attestationPayload.schemaId, + bytes32(0), + attester, + msg.sender, + uint64(block.timestamp), + attestationPayload.expirationDate, + 0, + version, + false, + attestationPayload.subject, + attestationPayload.attestationData + ); + attestations[attestation.attestationId] = attestation; + emit AttestationRegistered(attestation.attestationId); + } + + /** + * @notice Registers attestations to the AttestationRegistry + * @param attestationsPayloads the attestations payloads to create attestations and register them + */ + function bulkAttest(AttestationPayload[] calldata attestationsPayloads, address attester) public { + for (uint256 i = 0; i < attestationsPayloads.length; i++) { + attest(attestationsPayloads[i], attester); + } + } + + /** + * @notice Revokes an attestation for given identifier and can replace it by an other one + * @param attestationId the attestation ID to revoke + * @param replacedBy the replacing attestation ID (leave empty to just revoke) + */ + function revoke(bytes32 attestationId, bytes32 replacedBy) public { + if (!isRegistered(attestationId)) revert AttestationNotAttested(); + if (attestations[attestationId].revoked) revert AlreadyRevoked(); + if (msg.sender != attestations[attestationId].portal) revert OnlyAttestingPortal(); + if (!isRevocable(attestations[attestationId].portal)) revert AttestationNotRevocable(); + + attestations[attestationId].revoked = true; + attestations[attestationId].revocationDate = uint64(block.timestamp); + + if (isRegistered(replacedBy)) attestations[attestationId].replacedBy = replacedBy; + + emit AttestationRevoked(attestationId, replacedBy); + } + + /** + * @notice Bulk revokes attestations for given identifiers and can replace them by new ones + * @param attestationIds the attestations IDs to revoke + * @param replacedBy the replacing attestations IDs (leave an ID empty to just revoke) + */ + function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) external { + if (attestationIds.length != replacedBy.length) revert BulkRevocationInvalidParams(); + + for (uint256 i = 0; i < attestationIds.length; i++) { + revoke(attestationIds[i], replacedBy[i]); + } + } + + /** + * @notice Checks if an attestation is registered + * @param attestationId the attestation identifier + * @return true if the attestation is registered, false otherwise + */ + function isRegistered(bytes32 attestationId) public view returns (bool) { + return attestations[attestationId].attestationId != bytes32(0); + } + + /** + * @notice Checks whether a portal issues revocable attestations + * @param portalId the portal address (ID) + * @return true if the attestations issued by this portal are revocable, false otherwise + */ + function isRevocable(address portalId) public view returns (bool) { + PortalRegistry portalRegistry = PortalRegistry(router.getPortalRegistry()); + return portalRegistry.getPortalByAddress(portalId).isRevocable; + } + + /** + * @notice Gets an attestation by its identifier + * @param attestationId the attestation identifier + * @return the attestation + */ + function getAttestation(bytes32 attestationId) public view returns (Attestation memory) { + if (!isRegistered(attestationId)) revert AttestationNotAttested(); + return attestations[attestationId]; + } + + /** + * @notice Increments the registry version + * @return The new version number + */ + function incrementVersionNumber() public onlyOwner returns (uint16) { + ++version; + emit VersionUpdated(version); + return version; + } + + /** + * @notice Gets the registry version + * @return The current version number + */ + function getVersionNumber() public view returns (uint16) { + return version; + } + + /** + * @notice Gets the attestation id counter + * @return The attestationIdCounter + */ + function getAttestationIdCounter() public view returns (uint32) { + return attestationIdCounter; + } +} diff --git a/src/ModuleRegistry.sol b/src/ModuleRegistry.sol new file mode 100644 index 00000000..b709f778 --- /dev/null +++ b/src/ModuleRegistry.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AttestationPayload, Module } from "./types/Structs.sol"; +import { AbstractModule } from "./interface/AbstractModule.sol"; +import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { ERC165CheckerUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165CheckerUpgradeable.sol"; +import { PortalRegistry } from "./PortalRegistry.sol"; +import { IRouter } from "./interface/IRouter.sol"; + +/** + * @title Module Registry + * @author Consensys + * @notice This contract aims to manage the Modules used by the Portals, including their discoverability + */ +contract ModuleRegistry is OwnableUpgradeable { + IRouter public router; + /// @dev The list of Modules, accessed by their address + mapping(address id => Module module) public modules; + /// @dev The list of Module addresses + address[] public moduleAddresses; + + /// @notice Error thrown when an invalid Router address is given + error RouterInvalid(); + /// @notice Error thrown when a non-issuer tries to call a method that can only be called by an issuer + error OnlyIssuer(); + /// @notice Error thrown when an identical Module was already registered + error ModuleAlreadyExists(); + /// @notice Error thrown when attempting to add a Module without a name + error ModuleNameMissing(); + /// @notice Error thrown when attempting to add a Module without an address of deployed smart contract + error ModuleAddressInvalid(); + /// @notice Error thrown when attempting to add a Module which has not implemented the IModule interface + error ModuleInvalid(); + /// @notice Error thrown when attempting to run modules with no attestation payload provided + error AttestationPayloadMissing(); + /// @notice Error thrown when module is not registered + error ModuleNotRegistered(); + /// @notice Error thrown when module addresses and validation payload length mismatch + error ModuleValidationPayloadMismatch(); + + /// @notice Event emitted when a Module is registered + event ModuleRegistered(string name, string description, address moduleAddress); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /** + * @notice Contract initialization + */ + function initialize() public initializer { + __Ownable_init(); + } + + /** + * @notice Checks if the caller is a registered issuer. + * @param issuer the issuer address + */ + modifier onlyIssuers(address issuer) { + bool isIssuerRegistered = PortalRegistry(router.getPortalRegistry()).isIssuer(issuer); + if (!isIssuerRegistered) revert OnlyIssuer(); + _; + } + + /** + * @notice Changes the address for the Router + */ + function updateRouter(address _router) public onlyOwner { + if (_router == address(0)) revert RouterInvalid(); + router = IRouter(_router); + } + + /** + * Check if address is smart contract and not EOA + * @param contractAddress address to be verified + * @return the result as true if it is a smart contract else false + */ + function isContractAddress(address contractAddress) public view returns (bool) { + return contractAddress.code.length > 0; + } + + /** Register a Module, with its metadata and run some checks: + * - mandatory name + * - mandatory module's deployed smart contract address + * - the module must be unique + * @param name the module name + * @param description the module description + * @param moduleAddress the address of the deployed smart contract + * @dev the module is stored in a mapping, the number of modules is incremented and an event is emitted + */ + function register( + string memory name, + string memory description, + address moduleAddress + ) public onlyIssuers(msg.sender) { + if (bytes(name).length == 0) { + revert ModuleNameMissing(); + } + + // Check if moduleAddress is a smart contract address + if (!isContractAddress(moduleAddress)) { + revert ModuleAddressInvalid(); + } + + // Check if module has implemented AbstractModule + if (!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModule).interfaceId)) { + revert ModuleInvalid(); + } + + // Module address is used to identify uniqueness of the module + if (bytes(modules[moduleAddress].name).length > 0) { + revert ModuleAlreadyExists(); + } + + modules[moduleAddress] = Module(moduleAddress, name, description); + moduleAddresses.push(moduleAddress); + emit ModuleRegistered(name, description, moduleAddress); + } + + /** Execute the run method for all given Modules that are registered + * @param modulesAddresses the addresses of the registered modules + * @param attestationPayload the payload to attest + * @param validationPayload the payloads to check for each module + * @dev check if modules are registered and execute run method for each module + */ + function runModules( + address[] memory modulesAddresses, + AttestationPayload memory attestationPayload, + bytes[] memory validationPayload + ) public { + // If no modules provided, bypass module validation + if (modulesAddresses.length == 0) return; + // Each module involved must have a corresponding item from the validation payload + if (modulesAddresses.length != validationPayload.length) revert ModuleValidationPayloadMismatch(); + + // For each module check if it is registered and call run method + for (uint32 i = 0; i < modulesAddresses.length; i++) { + if (!isRegistered(modulesAddresses[i])) revert ModuleNotRegistered(); + AbstractModule(modulesAddresses[i]).run(attestationPayload, validationPayload, tx.origin); + } + } + + /** Execute the run method for all given Modules that are registered + * @param modulesAddresses the addresses of the registered modules + * @param attestationsPayloads the payloads to attest + * @param validationPayloads the payloads to check for each module + * @dev check if modules are registered and execute run method for each module + */ + function bulkRunModules( + address[] memory modulesAddresses, + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) public { + for (uint32 i = 0; i < modulesAddresses.length; i++) { + runModules(modulesAddresses, attestationsPayloads[i], validationPayloads[i]); + } + } + + /** + * @notice Get the number of Modules managed by the contract + * @return The number of Modules already registered + * @dev Returns the length of the `moduleAddresses` array + */ + function getModulesNumber() public view returns (uint256) { + return moduleAddresses.length; + } + + /** + * @notice Checks that a module is registered in the module registry + * @param moduleAddress The address of the Module to check + * @return True if the Module is registered, False otherwise + */ + function isRegistered(address moduleAddress) public view returns (bool) { + return bytes(modules[moduleAddress].name).length > 0; + } +} diff --git a/src/PortalRegistry.sol b/src/PortalRegistry.sol new file mode 100644 index 00000000..e602e2ce --- /dev/null +++ b/src/PortalRegistry.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { ERC165CheckerUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165CheckerUpgradeable.sol"; +import { AbstractPortal } from "./interface/AbstractPortal.sol"; +import { DefaultPortal } from "./portal/DefaultPortal.sol"; +import { Portal } from "./types/Structs.sol"; +import { IRouter } from "./interface/IRouter.sol"; + +/** + * @title Portal Registry + * @author Consensys + * @notice This contract aims to manage the Portals used by attestation issuers + */ +contract PortalRegistry is OwnableUpgradeable { + IRouter public router; + + mapping(address id => Portal portal) private portals; + + mapping(address issuerAddress => bool isIssuer) private issuers; + + address[] private portalAddresses; + + /// @notice Error thrown when an invalid Router address is given + error RouterInvalid(); + /// @notice Error thrown when a non-issuer tries to call a method that can only be called by an issuer + error OnlyIssuer(); + /// @notice Error thrown when attempting to register a Portal twice + error PortalAlreadyExists(); + /// @notice Error thrown when attempting to register a Portal that is not a smart contract + error PortalAddressInvalid(); + /// @notice Error thrown when attempting to register a Portal with an empty name + error PortalNameMissing(); + /// @notice Error thrown when attempting to register a Portal with an empty description + error PortalDescriptionMissing(); + /// @notice Error thrown when attempting to register a Portal with an empty owner name + error PortalOwnerNameMissing(); + /// @notice Error thrown when attempting to register a Portal that does not implement IPortal interface + error PortalInvalid(); + /// @notice Error thrown when attempting to get a Portal that is not registered + error PortalNotRegistered(); + + /// @notice Event emitted when a Portal registered + event PortalRegistered(string name, string description, address portalAddress); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /** + * @notice Contract initialization + */ + function initialize() public initializer { + __Ownable_init(); + } + + /** + * @notice Changes the address for the Router + */ + function updateRouter(address _router) public onlyOwner { + if (_router == address(0)) revert RouterInvalid(); + router = IRouter(_router); + } + + /** + * @notice Registers an address as been an issuer + * @param issuer the address to register as an issuer + */ + function setIssuer(address issuer) public onlyOwner { + issuers[issuer] = true; + } + + /** + * @notice Revokes issuer status from an address + * @param issuer the address to be revoked as an issuer + */ + function removeIssuer(address issuer) public onlyOwner { + issuers[issuer] = false; + } + + /** + * @notice Checks if a given address is an issuer + * @return A flag indicating whether the given address is an issuer + */ + function isIssuer(address issuer) public view returns (bool) { + return issuers[issuer]; + } + + /** + * @notice Checks if the caller is a registered issuer. + * @param issuer the issuer address + */ + modifier onlyIssuers(address issuer) { + if (!isIssuer(issuer)) revert OnlyIssuer(); + _; + } + + /** + * @notice Registers a Portal to the PortalRegistry + * @param id the portal address + * @param name the portal name + * @param description the portal description + * @param isRevocable whether the portal issues revocable attestations + * @param ownerName name of this portal's owner + */ + function register( + address id, + string memory name, + string memory description, + bool isRevocable, + string memory ownerName + ) public onlyIssuers(msg.sender) { + // Check if portal already exists + if (portals[id].id != address(0)) revert PortalAlreadyExists(); + + // Check if portal is a smart contract + if (!isContractAddress(id)) revert PortalAddressInvalid(); + + // Check if name is not empty + if (bytes(name).length == 0) revert PortalNameMissing(); + + // Check if description is not empty + if (bytes(description).length == 0) revert PortalDescriptionMissing(); + + // Check if the owner's name is not empty + if (bytes(ownerName).length == 0) revert PortalOwnerNameMissing(); + + // Check if portal has implemented AbstractPortal + if (!ERC165CheckerUpgradeable.supportsInterface(id, type(AbstractPortal).interfaceId)) revert PortalInvalid(); + + // Get the array of modules implemented by the portal + address[] memory modules = AbstractPortal(id).getModules(); + + // Add portal to mapping + Portal memory newPortal = Portal(id, msg.sender, modules, isRevocable, name, description, ownerName); + portals[id] = newPortal; + portalAddresses.push(id); + + // Emit event + emit PortalRegistered(name, description, id); + } + + /** + * @notice Deploys and registers a clone of default portal + * @param modules the modules addresses + * @param name the portal name + * @param description the portal description + * @param ownerName name of this portal's owner + */ + function deployDefaultPortal( + address[] calldata modules, + string memory name, + string memory description, + bool isRevocable, + string memory ownerName + ) external onlyIssuers(msg.sender) { + DefaultPortal defaultPortal = new DefaultPortal(); + defaultPortal.initialize(modules, address(router)); + register(address(defaultPortal), name, description, isRevocable, ownerName); + } + + /** + * @notice Get a Portal by its address + * @param id The address of the Portal + * @return The Portal + */ + function getPortalByAddress(address id) public view returns (Portal memory) { + if (!isRegistered(id)) revert PortalNotRegistered(); + return portals[id]; + } + + /** + * @notice Check if a Portal is registered + * @param id The address of the Portal + * @return True if the Portal is registered, false otherwise + */ + function isRegistered(address id) public view returns (bool) { + return portals[id].id != address(0); + } + + /** + * @notice Get the number of Portals managed by the contract + * @return The number of Portals already registered + * @dev Returns the length of the `portalAddresses` array + */ + function getPortalsCount() public view returns (uint256) { + return portalAddresses.length; + } + + /** + * Check if address is smart contract and not EOA + * @param contractAddress address to be verified + * @return the result as true if it is a smart contract else false + */ + function isContractAddress(address contractAddress) internal view returns (bool) { + return contractAddress.code.length > 0; + } +} diff --git a/src/Router.sol b/src/Router.sol new file mode 100644 index 00000000..31d2ecd4 --- /dev/null +++ b/src/Router.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import { IRouter } from "./interface/IRouter.sol"; + +/** + * @title Router + * @author Consensys + * @notice This contract aims to provides a single entrypoint for the Verax registries + */ +contract Router is IRouter, OwnableUpgradeable { + address private ATTESTATION_REGISTRY; + address private MODULE_REGISTRY; + address private PORTAL_REGISTRY; + address private SCHEMA_REGISTRY; + + event AttestationRegistryUpdated(address indexed registryAddress); + event ModuleRegistryUpdated(address indexed registryAddress); + event PortalRegistryUpdated(address indexed registryAddress); + event SchemaRegistryUpdated(address indexed registryAddress); + + function initialize() public initializer { + __Ownable_init(); + } + + function getAttestationRegistry() external view override returns (address) { + return ATTESTATION_REGISTRY; + } + + function updateAttestationRegistry(address _attestationRegistry) public onlyOwner { + ATTESTATION_REGISTRY = _attestationRegistry; + emit AttestationRegistryUpdated(_attestationRegistry); + } + + function getModuleRegistry() external view override returns (address) { + return MODULE_REGISTRY; + } + + function updateModuleRegistry(address _moduleRegistry) public onlyOwner { + MODULE_REGISTRY = _moduleRegistry; + emit ModuleRegistryUpdated(_moduleRegistry); + } + + function getPortalRegistry() external view override returns (address) { + return PORTAL_REGISTRY; + } + + function updatePortalRegistry(address _portalRegistry) public onlyOwner { + PORTAL_REGISTRY = _portalRegistry; + emit PortalRegistryUpdated(_portalRegistry); + } + + function getSchemaRegistry() external view override returns (address) { + return SCHEMA_REGISTRY; + } + + function updateSchemaRegistry(address _schemaRegistry) public onlyOwner { + SCHEMA_REGISTRY = _schemaRegistry; + emit SchemaRegistryUpdated(_schemaRegistry); + } +} diff --git a/src/SchemaRegistry.sol b/src/SchemaRegistry.sol new file mode 100644 index 00000000..9c1318ad --- /dev/null +++ b/src/SchemaRegistry.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import { Schema } from "./types/Structs.sol"; +import { PortalRegistry } from "./PortalRegistry.sol"; +import { IRouter } from "./interface/IRouter.sol"; + +/** + * @title Schema Registry + * @author Consensys + * @notice This contract aims to manage the Schemas used by the Portals, including their discoverability + */ +contract SchemaRegistry is OwnableUpgradeable { + IRouter public router; + /// @dev The list of Schemas, accessed by their ID + mapping(bytes32 id => Schema schema) private schemas; + /// @dev The list of Schema IDs + bytes32[] public schemaIds; + + /// @notice Error thrown when an invalid Router address is given + error RouterInvalid(); + /// @notice Error thrown when a non-issuer tries to call a method that can only be called by an issuer + error OnlyIssuer(); + /// @notice Error thrown when an identical Schema was already registered + error SchemaAlreadyExists(); + /// @notice Error thrown when attempting to add a Schema without a name + error SchemaNameMissing(); + /// @notice Error thrown when attempting to add a Schema without a string to define it + error SchemaStringMissing(); + /// @notice Error thrown when attempting to add a Schema without a context + error SchemaContextMissing(); + /// @notice Error thrown when attempting to get a Schema that is not registered + error SchemaNotRegistered(); + + /// @notice Event emitted when a Schema is created and registered + event SchemaCreated(bytes32 indexed id, string name, string description, string context, string schemaString); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /** + * @notice Contract initialization + */ + function initialize() public initializer { + __Ownable_init(); + } + + /** + * @notice Checks if the caller is a registered issuer. + * @param issuer the issuer address + */ + modifier onlyIssuers(address issuer) { + bool isIssuerRegistered = PortalRegistry(router.getPortalRegistry()).isIssuer(issuer); + if (!isIssuerRegistered) revert OnlyIssuer(); + _; + } + + /** + * @notice Changes the address for the Router + */ + function updateRouter(address _router) public onlyOwner { + if (_router == address(0)) revert RouterInvalid(); + router = IRouter(_router); + } + + /** + * Generate an ID for a given schema + * @param schema the string defining a schema + * @return the schema ID + * @dev encodes a schema string to unique bytes + */ + function getIdFromSchemaString(string memory schema) public pure returns (bytes32) { + return keccak256(abi.encodePacked(schema)); + } + + /** Create a Schema, with its metadata and run some checks: + * - mandatory name + * - mandatory string defining the schema + * - the Schema must be unique + * @param name the Schema name + * @param description the Schema description + * @param context the Schema context + * @param schemaString the string defining a Schema + * @dev the Schema is stored in a mapping, its ID is added to an array of IDs and an event is emitted + */ + function createSchema( + string memory name, + string memory description, + string memory context, + string memory schemaString + ) public onlyIssuers(msg.sender) { + if (bytes(name).length == 0) revert SchemaNameMissing(); + if (bytes(schemaString).length == 0) revert SchemaStringMissing(); + if (bytes(context).length == 0) revert SchemaContextMissing(); + + bytes32 schemaId = getIdFromSchemaString(schemaString); + + if (isRegistered(schemaId)) { + revert SchemaAlreadyExists(); + } + + schemas[schemaId] = Schema(name, description, context, schemaString); + schemaIds.push(schemaId); + emit SchemaCreated(schemaId, name, description, context, schemaString); + } + + /** + * @notice Gets a schema by its identifier + * @param schemaId the schema ID + * @return the schema + */ + function getSchema(bytes32 schemaId) public view returns (Schema memory) { + if (!isRegistered(schemaId)) revert SchemaNotRegistered(); + return schemas[schemaId]; + } + + /** + * @notice Get the number of Schemas managed by the contract + * @return The number of Schemas already registered + * @dev Returns the length of the `schemaIds` array + */ + function getSchemasNumber() public view returns (uint256) { + return schemaIds.length; + } + + /** + * @notice Check if a Schema is registered + * @param schemaId The ID of the Schema + * @return True if the Schema is registered, false otherwise + */ + function isRegistered(bytes32 schemaId) public view returns (bool) { + return bytes(schemas[schemaId].name).length > 0; + } +} diff --git a/src/example/CorrectModule.sol b/src/example/CorrectModule.sol new file mode 100644 index 00000000..77de4b09 --- /dev/null +++ b/src/example/CorrectModule.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractModule } from "../interface/AbstractModule.sol"; +import { AttestationPayload } from "../types/Structs.sol"; +// solhint-disable-next-line max-line-length +import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; + +contract CorrectModule is AbstractModule, IERC165Upgradeable { + function test() public {} + + function run( + AttestationPayload memory /*attestationPayload*/, + bytes[] memory validationPayload, + address /*txSender*/ + ) public pure override returns (bytes[] memory) { + return (validationPayload); + } + + function supportsInterface(bytes4 interfaceID) public pure override returns (bool) { + return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; + } +} diff --git a/src/example/EASPortal.sol b/src/example/EASPortal.sol new file mode 100644 index 00000000..0e91042c --- /dev/null +++ b/src/example/EASPortal.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractPortal } from "../interface/AbstractPortal.sol"; +import { AttestationPayload } from "../types/Structs.sol"; + +/** + * @title EAS Portal + * @notice This is an example of how to maintain interoperability with EAS - https://attest.sh + */ +contract EASPortal is AbstractPortal { + // @notice This struct is defined in EAS's contracts' codebase + // solhint-disable-next-line max-line-length + // this definition was taken from: https://github.com/ethereum-attestation-service/eas-contracts/blob/master/contracts/IEAS.sol#L9 + struct AttestationRequestData { + address recipient; + uint64 expirationTime; + bool revocable; + bytes32 refUID; + bytes data; + uint256 value; + } + + // @notice This struct is defined in EAS's contracts' codebase + // solhint-disable-next-line max-line-length + // definition taken from: https://github.com/ethereum-attestation-service/eas-contracts/blob/master/contracts/IEAS.sol#L19 + struct AttestationRequest { + bytes32 schema; + AttestationRequestData data; + } + + /// @notice Error thrown when trying to revoke an attestation + error NoRevocation(); + /// @notice Error thrown when trying to bulk revoke attestations + error NoBulkRevocation(); + + function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {} + + function _afterAttest() internal override {} + + function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} + + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal override {} + + function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} + + function attest(AttestationRequest memory attestationRequest) external payable { + bytes[] memory validationPayload = new bytes[](0); + + AttestationPayload memory attestationPayload = AttestationPayload( + attestationRequest.schema, + attestationRequest.data.expirationTime, + abi.encodePacked(attestationRequest.data.recipient), + attestationRequest.data.data + ); + + super.attest(attestationPayload, validationPayload); + } + + function bulkAttest(AttestationRequest[] memory attestationsRequests) public payable { + AttestationPayload[] memory attestationsPayloads = new AttestationPayload[](attestationsRequests.length); + bytes[][] memory validationPayloads = new bytes[][](attestationsRequests.length); + + for (uint256 i = 0; i < attestationsRequests.length; i++) { + attestationsPayloads[i] = AttestationPayload( + attestationsRequests[i].schema, + attestationsRequests[i].data.expirationTime, + abi.encodePacked(attestationsRequests[i].data.recipient), + attestationsRequests[i].data.data + ); + + validationPayloads[i] = new bytes[](0); + } + + super.bulkAttest(attestationsPayloads, validationPayloads); + } + + function revoke(bytes32 /*attestationId*/, bytes32 /*replacedBy*/) public pure override { + revert NoRevocation(); + } + + function bulkRevoke(bytes32[] memory /*attestationIds*/, bytes32[] memory /*replacedBy*/) public pure override { + revert NoBulkRevocation(); + } + + function _getAttester() public view override returns (address) { + return msg.sender; + } +} diff --git a/src/example/IncorrectModule.sol b/src/example/IncorrectModule.sol new file mode 100644 index 00000000..73211a1e --- /dev/null +++ b/src/example/IncorrectModule.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +contract IncorrectModule {} diff --git a/src/example/MsgSenderModule.sol b/src/example/MsgSenderModule.sol new file mode 100644 index 00000000..d195c57a --- /dev/null +++ b/src/example/MsgSenderModule.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractModule } from "../interface/AbstractModule.sol"; +// solhint-disable-next-line max-line-length +import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; +import { Initializable } from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import { AttestationPayload } from "../types/Structs.sol"; + +/** + * @title Msg Sender Module + * @author Consensys + * @notice This contract is an example of a module, able to check if the transaction sender is a given address + */ +contract MsgSenderModule is IERC165Upgradeable, AbstractModule, Initializable { + /// @dev The address expected by this module + address public expectedMsgSender; + + /// @notice Error thrown when the transaction sender is not the expected address + error WrongTransactionSender(); + + /** + * @notice Contract initialization + */ + function initialize(address _expectedMsgSender) public initializer { + expectedMsgSender = _expectedMsgSender; + } + + /** + * @notice The main method for the module, running the check + */ + function run( + AttestationPayload memory /*_attestationPayload*/, + bytes[] memory _validationPayload, + address _txSender + ) public view override returns (bytes[] memory validationPayload) { + validationPayload = _validationPayload; + if (_txSender != expectedMsgSender) { + revert WrongTransactionSender(); + } + } + + /** + * @notice To check this contract implements the Module interface + */ + function supportsInterface(bytes4 interfaceID) external pure returns (bool) { + return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; + } +} diff --git a/src/interface/AbstractModule.sol b/src/interface/AbstractModule.sol new file mode 100644 index 00000000..4776fca3 --- /dev/null +++ b/src/interface/AbstractModule.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AttestationPayload } from "../types/Structs.sol"; + +abstract contract AbstractModule { + function run( + AttestationPayload memory attestationPayload, + bytes[] memory validationPayload, + address txSender + ) public virtual returns (bytes[] memory moduleValidationPayload); +} diff --git a/src/interface/AbstractPortal.sol b/src/interface/AbstractPortal.sol new file mode 100644 index 00000000..a7aaae44 --- /dev/null +++ b/src/interface/AbstractPortal.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AttestationRegistry } from "../AttestationRegistry.sol"; +import { ModuleRegistry } from "../ModuleRegistry.sol"; +import { PortalRegistry } from "../PortalRegistry.sol"; +import { AttestationPayload } from "../types/Structs.sol"; +// solhint-disable-next-line max-line-length +import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol"; +import { Initializable } from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import { IRouter } from "../interface/IRouter.sol"; + +abstract contract AbstractPortal is Initializable, IERC165Upgradeable { + IRouter public router; + address[] public modules; + ModuleRegistry public moduleRegistry; + AttestationRegistry public attestationRegistry; + PortalRegistry public portalRegistry; + + /// @notice Error thrown when the numbers of modules to go through and payloads for them is not the same + error ModulePayloadMismatch(); + /// @notice Error thrown when someone else than the portal's owner is trying to revoke + error OnlyPortalOwner(); + + /** + * @notice Contract initialization + * @param _modules list of modules to use for the portal (can be empty) + * @param _router Router's address + */ + function initialize(address[] calldata _modules, address _router) public virtual initializer { + // Store addresses for linked modules, ModuleRegistry and AttestationRegistry + modules = _modules; + router = IRouter(_router); + attestationRegistry = AttestationRegistry(router.getAttestationRegistry()); + moduleRegistry = ModuleRegistry(router.getModuleRegistry()); + portalRegistry = PortalRegistry(router.getPortalRegistry()); + } + + /** + * @notice attest the schema with given attestationPayload and validationPayload + * @param attestationPayload the payload to attest + * @param validationPayload the payload to validate via the modules to issue the attestations + * @dev Runs all modules for the portal and registers the attestation using AttestationRegistry + */ + function attest( + AttestationPayload memory attestationPayload, + bytes[] memory validationPayload + ) public payable virtual { + if (modules.length != 0) _runModules(attestationPayload, validationPayload); + + _beforeAttest(attestationPayload, msg.value); + + attestationRegistry.attest(attestationPayload, _getAttester()); + + _afterAttest(); + } + + /** + * @notice Bulk attest the schema with payloads to attest and validation payloads + * @param attestationsPayloads the payloads to attest + * @param validationPayloads the payloads to validate via the modules to issue the attestations + */ + function bulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) public payable virtual { + _onBulkAttest(attestationsPayloads, validationPayloads); + // Run all modules for all payloads + moduleRegistry.bulkRunModules(modules, attestationsPayloads, validationPayloads); + // Register attestations using the attestation registry + attestationRegistry.bulkAttest(attestationsPayloads, _getAttester()); + } + + /** + * @notice Revokes the attestation for the given identifier and can replace it by a new one + * @param attestationId the attestation ID to revoke + * @param replacedBy the replacing attestation ID (leave empty to just revoke) + * @dev By default, revocation is only possible by the portal owner + * We strongly encourage implementing such a rule in your Portal if you intend on overriding this method + */ + function revoke(bytes32 attestationId, bytes32 replacedBy) public virtual { + if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + _onRevoke(attestationId, replacedBy); + attestationRegistry.revoke(attestationId, replacedBy); + } + + /** + * @notice Bulk revokes attestations for given identifiers and can replace them by new ones + * @param attestationIds the attestations IDs to revoke + * @param replacedBy the replacing attestations IDs (leave an ID empty to just revoke) + */ + function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public virtual { + _onBulkRevoke(attestationIds, replacedBy); + attestationRegistry.bulkRevoke(attestationIds, replacedBy); + } + + /** + * @notice Get all the modules addresses used by the Portal + * @return The list of modules addresses linked to the Portal + */ + function getModules() external view returns (address[] memory) { + return modules; + } + + /** + * @notice Verifies that a specific interface is implemented by the Portal, following ERC-165 specification + * @param interfaceID the interface identifier checked in this call + * @return The list of modules addresses linked to the Portal + */ + function supportsInterface(bytes4 interfaceID) public pure virtual override returns (bool) { + return interfaceID == type(AbstractPortal).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; + } + + /** + * @notice Runs all the modules linked to the Portal to check their logic against the validation payload + * @param attestationPayload the attestation payload supposed to be attested + * @param validationPayload the list of payloads used by modules + * @dev Each module must have its own item in the list of validation payloads + */ + function _runModules(AttestationPayload memory attestationPayload, bytes[] memory validationPayload) internal { + if (modules.length != validationPayload.length) revert ModulePayloadMismatch(); + moduleRegistry.runModules(modules, attestationPayload, validationPayload); + } + + /** + * @notice Optional method run before a payload is attested + * @param attestationPayload the attestation payload supposed to be attested + * @param value the optional ETH value paid for this attestation + */ + function _beforeAttest(AttestationPayload memory attestationPayload, uint256 value) internal virtual; + + /** + * @notice Optional method run after a payload is attested + */ + function _afterAttest() internal virtual; + + /** + * @notice Optional method run when attesting a batch of payloads + * @param attestationsPayloads the payloads to attest + * @param validationPayloads the payloads to validate in order to issue the attestations + */ + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal virtual; + + /** + * @notice Optional method run when an attestation is revoked or replaced + * @param attestationId the attestation ID to revoke + * @param replacedBy the replacing attestation ID + */ + function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal virtual; + + /** + * @notice Optional method run when a batch of attestations are revoked or replaced + * @param attestationIds the attestations IDs to revoke + * @param replacedBy the replacing attestations IDs + */ + function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal virtual; + + /** + * @notice Defines the address of the entity issuing attestations to the subject + * @dev We strongly encourage a reflection when overriding this rule: who should be set as the attester? + */ + function _getAttester() public view virtual returns (address) { + return msg.sender; + } +} diff --git a/src/interface/IRouter.sol b/src/interface/IRouter.sol new file mode 100644 index 00000000..ef6b4789 --- /dev/null +++ b/src/interface/IRouter.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +interface IRouter { + function getAttestationRegistry() external view returns (address); + + function getModuleRegistry() external view returns (address); + + function getPortalRegistry() external view returns (address); + + function getSchemaRegistry() external view returns (address); +} diff --git a/src/portal/DefaultPortal.sol b/src/portal/DefaultPortal.sol new file mode 100644 index 00000000..e901c0a0 --- /dev/null +++ b/src/portal/DefaultPortal.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractPortal } from "../interface/AbstractPortal.sol"; +import { AttestationPayload } from "../types/Structs.sol"; + +/** + * @title Default Portal + * @author Consensys + * @notice This contract aims to provide a default portal + * @dev This Portal does not add any logic to the AbstractPortal + */ +contract DefaultPortal is AbstractPortal { + function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {} + + function _afterAttest() internal override {} + + function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} + + function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} + + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal override {} +} diff --git a/src/types/Structs.sol b/src/types/Structs.sol new file mode 100644 index 00000000..5080b449 --- /dev/null +++ b/src/types/Structs.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +struct AttestationPayload { + bytes32 schemaId; // The identifier of the schema this attestation adheres to. + uint64 expirationDate; // The expiration date of the attestation. + bytes subject; // The ID of the attestee, EVM address, DID, URL etc. + bytes attestationData; // The attestation data. +} + +struct Attestation { + bytes32 attestationId; // The unique identifier of the attestation. + bytes32 schemaId; // The identifier of the schema this attestation adheres to. + bytes32 replacedBy; // Whether the attestation was replaced by a new one. + address attester; // The address issuing the attestation to the subject. + address portal; // The id of the portal that created the attestation. + uint64 attestedDate; // The date the attestation is issued. + uint64 expirationDate; // The expiration date of the attestation. + uint64 revocationDate; // The date when the attestation was revoked. + uint16 version; // Version of the registry when the attestation was created. + bool revoked; // Whether the attestation is revoked or not. + bytes subject; // The ID of the attestee, EVM address, DID, URL etc. + bytes attestationData; // The attestation data. +} + +struct Schema { + string name; // The name of the schema. + string description; // A description of the schema. + string context; // The context of the schema. + string schema; // The schema definition. +} + +struct Portal { + address id; // The unique identifier of the portal. + address ownerAddress; // The address of the owner of this portal. + address[] modules; // Addresses of modules implemented by the portal. + bool isRevocable; // Whether attestations issued can be revoked. + string name; // The name of the portal. + string description; // A description of the portal. + string ownerName; // The name of the owner of this portal. +} + +struct Module { + address moduleAddress; // The address of the module. + string name; // The name of the module. + string description; // A description of the module. +} diff --git a/test/AttestationRegistry.t.sol b/test/AttestationRegistry.t.sol new file mode 100644 index 00000000..1dca61eb --- /dev/null +++ b/test/AttestationRegistry.t.sol @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { AttestationRegistry } from "../src/AttestationRegistry.sol"; +import { PortalRegistryMock } from "./mocks/PortalRegistryMock.sol"; +import { PortalRegistry } from "../src/PortalRegistry.sol"; +import { SchemaRegistryMock } from "./mocks/SchemaRegistryMock.sol"; +import { Attestation, AttestationPayload } from "../src/types/Structs.sol"; +import { Router } from "../src/Router.sol"; + +contract AttestationRegistryTest is Test { + address public portal = makeAddr("portal"); + address public user = makeAddr("user"); + address public attester = makeAddr("attester"); + Router public router; + AttestationRegistry public attestationRegistry; + address public portalRegistryAddress; + address public schemaRegistryAddress; + + event Initialized(uint8 version); + event AttestationRegistered(bytes32 indexed attestationId); + event BulkAttestationsRegistered(Attestation[] attestations); + event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + event VersionUpdated(uint16 version); + + function setUp() public { + router = new Router(); + router.initialize(); + + attestationRegistry = new AttestationRegistry(); + router.updateAttestationRegistry(address(attestationRegistry)); + + portalRegistryAddress = address(new PortalRegistryMock()); + schemaRegistryAddress = address(new SchemaRegistryMock()); + vm.prank(address(0)); + attestationRegistry.updateRouter(address(router)); + + router.updatePortalRegistry(portalRegistryAddress); + router.updateSchemaRegistry(schemaRegistryAddress); + + PortalRegistry(portalRegistryAddress).register(portal, "Name", "Description", true, "Owner name"); + } + + function test_initialize_ContractAlreadyInitialized() public { + vm.expectRevert("Initializable: contract is already initialized"); + attestationRegistry.initialize(); + } + + function test_updateRouter() public { + AttestationRegistry testAttestationRegistry = new AttestationRegistry(); + + vm.prank(address(0)); + testAttestationRegistry.updateRouter(address(1)); + address routerAddress = address(testAttestationRegistry.router()); + assertEq(routerAddress, address(1)); + } + + function test_updateRouter_InvalidParameter() public { + AttestationRegistry testAttestationRegistry = new AttestationRegistry(); + + vm.expectRevert(AttestationRegistry.RouterInvalid.selector); + vm.prank(address(0)); + testAttestationRegistry.updateRouter(address(0)); + } + + function test_attest(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + Attestation memory attestation = _createAttestation(attestationPayload, 1); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(attestation.attestationId); + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + + Attestation memory registeredAttestation = attestationRegistry.getAttestation(attestation.attestationId); + _assertAttestation(attestation, registeredAttestation); + } + + function test_attest_SchemaNotRegistered(AttestationPayload memory attestationPayload) public { + vm.expectRevert(AttestationRegistry.SchemaNotRegistered.selector); + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + } + + function test_attest_AttestationSubjectFieldEmpty(AttestationPayload memory attestationPayload) public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + attestationPayload.subject = ""; + + vm.expectRevert(AttestationRegistry.AttestationSubjectFieldEmpty.selector); + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + } + + function test_attest_AttestationDataFieldEmpty(AttestationPayload memory attestationPayload) public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + attestationPayload.subject = "subject"; + + attestationPayload.attestationData = ""; + + vm.expectRevert(AttestationRegistry.AttestationDataFieldEmpty.selector); + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + } + + function test_attest_PortalNotRegistered(AttestationPayload memory attestationPayload) public { + vm.expectRevert(AttestationRegistry.OnlyPortal.selector); + vm.prank(user); + attestationRegistry.attest(attestationPayload, attester); + } + + function test_bulkAttest(AttestationPayload[2] memory attestationsPayloads) public { + vm.assume(attestationsPayloads[0].subject.length != 0); + vm.assume(attestationsPayloads[0].attestationData.length != 0); + vm.assume(attestationsPayloads[1].subject.length != 0); + vm.assume(attestationsPayloads[1].attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationsPayloads[0].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationsPayloads[1].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + Attestation memory attestation1 = _createAttestation(attestationsPayloads[0], 1); + Attestation memory attestation2 = _createAttestation(attestationsPayloads[1], 2); + + Attestation[] memory attestations = new Attestation[](2); + attestations[0] = attestation1; + attestations[1] = attestation2; + + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationsPayloads[0]; + payloadsToAttest[1] = attestationsPayloads[1]; + + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(attestations[0].attestationId); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(attestations[1].attestationId); + vm.prank(portal); + + attestationRegistry.bulkAttest(payloadsToAttest, attester); + } + + function test_revoke(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + vm.startPrank(portal, attester); + attestationRegistry.attest(attestationPayload, attester); + // Assert initial state is a valid attestation + bytes32 attestationId = bytes32(abi.encode(1)); + Attestation memory registeredAttestation = attestationRegistry.getAttestation(attestationId); + + assertEq(registeredAttestation.attestationId, bytes32(abi.encode(1))); + assertFalse(registeredAttestation.revoked); + assertEq(registeredAttestation.revocationDate, 0); + assertEq(registeredAttestation.replacedBy, bytes32(0)); + assertEq(registeredAttestation.portal, portal); + assertEq(registeredAttestation.attester, attester); + + vm.expectEmit(true, true, true, true); + emit AttestationRevoked(attestationId, bytes32(0)); + attestationRegistry.revoke(attestationId, bytes32(0)); + vm.stopPrank(); + + // Assert final state is a revoked attestation + Attestation memory revokedAttestation = attestationRegistry.getAttestation(bytes32(abi.encode(1))); + assertTrue(revokedAttestation.revoked); + assertEq(revokedAttestation.revocationDate, block.timestamp); + assertEq(revokedAttestation.replacedBy, bytes32(0)); + } + + function test_revoke_AttestationAlreadyRevoked(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + vm.startPrank(portal, attester); + attestationRegistry.attest(attestationPayload, attester); + + vm.expectEmit(); + emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(0)); + attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + + vm.expectRevert(AttestationRegistry.AlreadyRevoked.selector); + attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + + vm.stopPrank(); + } + + function test_revoke_AttestationNotAttested() public { + vm.expectRevert(AttestationRegistry.AttestationNotAttested.selector); + attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + } + + function test_revoke_OnlyAttestingPortal(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + + vm.expectRevert(AttestationRegistry.OnlyAttestingPortal.selector); + vm.prank(user); + attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + } + + function test_revoke_AttestationNotRevocable(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + address nonRevocablePortalAddress = makeAddr("nonRevocablePortalAddress"); + PortalRegistry(portalRegistryAddress).register( + nonRevocablePortalAddress, + "Name", + "Description", + false, + "Owner name" + ); + + vm.startPrank(nonRevocablePortalAddress, attester); + + attestationRegistry.attest(attestationPayload, attester); + + vm.expectRevert(AttestationRegistry.AttestationNotRevocable.selector); + attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + + vm.stopPrank(); + } + + function test_revokeAndReplace( + AttestationPayload memory attestationPayloadOrigin, + AttestationPayload memory attestationPayloadReplacement + ) public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + vm.assume(attestationPayloadOrigin.subject.length != 0); + vm.assume(attestationPayloadOrigin.attestationData.length != 0); + attestationPayloadOrigin.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + vm.assume(attestationPayloadReplacement.subject.length != 0); + vm.assume(attestationPayloadReplacement.attestationData.length != 0); + attestationPayloadReplacement.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + vm.startPrank(portal, attester); + + attestationRegistry.attest(attestationPayloadOrigin, attester); + attestationRegistry.attest(attestationPayloadReplacement, attester); + + // Do revert and replace the attestation + vm.expectEmit(true, true, true, true); + emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(abi.encode(2))); + attestationRegistry.revoke(bytes32(abi.encode(1)), bytes32(abi.encode(2))); + + vm.stopPrank(); + + // Assert final state is a revoked and replaced attestation + Attestation memory revokedAttestation = attestationRegistry.getAttestation(bytes32(abi.encode(1))); + assertTrue(revokedAttestation.revoked); + assertEq(revokedAttestation.revocationDate, block.timestamp); + assertEq(revokedAttestation.replacedBy, bytes32(abi.encode(2))); + } + + function test_bulkRevoke(AttestationPayload[3] memory attestationPayloads) public { + vm.assume(attestationPayloads[0].subject.length != 0); + vm.assume(attestationPayloads[0].attestationData.length != 0); + vm.assume(attestationPayloads[1].subject.length != 0); + vm.assume(attestationPayloads[1].attestationData.length != 0); + vm.assume(attestationPayloads[2].subject.length != 0); + vm.assume(attestationPayloads[2].attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayloads[0].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayloads[1].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayloads[2].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + vm.startPrank(portal, attester); + + attestationRegistry.attest(attestationPayloads[0], attester); + attestationRegistry.attest(attestationPayloads[1], attester); + attestationRegistry.attest(attestationPayloads[2], attester); + + bytes32 attestationId1 = bytes32(abi.encode(1)); + bytes32 attestationId2 = bytes32(abi.encode(2)); + bytes32 attestationId3 = bytes32(abi.encode(3)); + + // Assert initial state is a valid attestation + Attestation memory registeredAttestation1 = attestationRegistry.getAttestation(attestationId1); + + assertEq(registeredAttestation1.attestationId, attestationId1); + assertFalse(registeredAttestation1.revoked); + assertEq(registeredAttestation1.revocationDate, 0); + assertEq(registeredAttestation1.replacedBy, bytes32(0)); + assertEq(registeredAttestation1.portal, portal); + assertEq(registeredAttestation1.attester, attester); + + Attestation memory registeredAttestation2 = attestationRegistry.getAttestation(attestationId2); + + assertEq(registeredAttestation2.attestationId, attestationId2); + assertFalse(registeredAttestation2.revoked); + assertEq(registeredAttestation2.revocationDate, 0); + assertEq(registeredAttestation2.replacedBy, bytes32(0)); + assertEq(registeredAttestation2.portal, portal); + assertEq(registeredAttestation2.attester, attester); + + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = attestationId1; + attestationsToRevoke[1] = attestationId2; + bytes32[] memory replacingAttestations = new bytes32[](2); + replacingAttestations[0] = bytes32(0); + replacingAttestations[1] = attestationId3; + + vm.expectEmit(true, true, true, true); + emit AttestationRevoked(attestationsToRevoke[0], replacingAttestations[0]); + vm.expectEmit(true, true, true, true); + emit AttestationRevoked(attestationsToRevoke[1], replacingAttestations[1]); + + attestationRegistry.bulkRevoke(attestationsToRevoke, replacingAttestations); + vm.stopPrank(); + + // Assert final state is a revoked attestation and a replaced attestation + Attestation memory revokedAttestation1 = attestationRegistry.getAttestation(attestationId1); + assertTrue(revokedAttestation1.revoked); + assertEq(revokedAttestation1.revocationDate, block.timestamp); + assertEq(revokedAttestation1.replacedBy, bytes32(0)); + + Attestation memory revokedAttestation2 = attestationRegistry.getAttestation(attestationId2); + assertTrue(revokedAttestation2.revoked); + assertEq(revokedAttestation2.revocationDate, block.timestamp); + assertEq(revokedAttestation2.replacedBy, attestationId3); + } + + function test_bulkRevoke_InvalidParams() public { + bytes32 attestationId1 = bytes32(abi.encode(1)); + bytes32 attestationId2 = bytes32(abi.encode(2)); + + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = attestationId1; + attestationsToRevoke[1] = attestationId2; + bytes32[] memory replacingAttestations = new bytes32[](1); + replacingAttestations[0] = bytes32(0); + + vm.expectRevert(AttestationRegistry.BulkRevocationInvalidParams.selector); + attestationRegistry.bulkRevoke(attestationsToRevoke, replacingAttestations); + } + + function test_isRevocable() public { + bool isRevocable = attestationRegistry.isRevocable(portal); + assertTrue(isRevocable); + } + + function test_isNotRevocable() public { + address nonRevocablePortal = makeAddr("nonRevocablePortal"); + PortalRegistry(portalRegistryAddress).register(nonRevocablePortal, "Name", "Description", false, "Owner name"); + + bool isRevocable = attestationRegistry.isRevocable(nonRevocablePortal); + assertFalse(isRevocable); + } + + function test_isRegistered(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + bool isRegistered = attestationRegistry.isRegistered(bytes32(abi.encode(1))); + assertFalse(isRegistered); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + Attestation memory attestation = _createAttestation(attestationPayload, 1); + + vm.startPrank(portal); + attestationRegistry.attest(attestationPayload, attester); + + isRegistered = attestationRegistry.isRegistered(attestation.attestationId); + assertTrue(isRegistered); + + isRegistered = attestationRegistry.isRegistered(bytes32(0)); + assertFalse(isRegistered); + } + + function test_getAttestation(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + Attestation memory attestation = _createAttestation(attestationPayload, 1); + + vm.startPrank(portal); + attestationRegistry.attest(attestationPayload, attester); + + Attestation memory registeredAttestation = attestationRegistry.getAttestation(attestation.attestationId); + _assertAttestation(attestation, registeredAttestation); + } + + function test_getAttestation_AttestationNotAttested() public { + vm.expectRevert(AttestationRegistry.AttestationNotAttested.selector); + attestationRegistry.getAttestation(bytes32(abi.encode(1))); + } + + function test_incrementVersionNumber() public { + assertEq(attestationRegistry.getVersionNumber(), 0); + for (uint16 i = 1; i <= 5; i++) { + vm.expectEmit(true, true, true, true); + emit VersionUpdated(i); + vm.prank(address(0)); + uint256 version = attestationRegistry.incrementVersionNumber(); + assertEq(version, i); + uint16 newVersion = attestationRegistry.getVersionNumber(); + assertEq(newVersion, i); + } + } + + function test_getAttestationIdCounter(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + uint32 version = attestationRegistry.getAttestationIdCounter(); + + assertEq(version, 0); + + vm.startPrank(portal); + + attestationRegistry.attest(attestationPayload, attester); + + version = attestationRegistry.getAttestationIdCounter(); + assertEq(version, 1); + + attestationRegistry.attest(attestationPayload, attester); + + version = attestationRegistry.getAttestationIdCounter(); + assertEq(version, 2); + + vm.stopPrank(); + } + + function _createAttestation( + AttestationPayload memory attestationPayload, + uint256 id + ) internal returns (Attestation memory) { + uint16 versionNumber = attestationRegistry.getVersionNumber(); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + Attestation memory attestation = Attestation( + bytes32(abi.encode(id)), + attestationPayload.schemaId, + bytes32(0), + attester, + portal, + uint64(block.timestamp), + attestationPayload.expirationDate, + 0, + versionNumber, + false, + attestationPayload.subject, + attestationPayload.attestationData + ); + return attestation; + } + + function _assertAttestation(Attestation memory attestation1, Attestation memory attestation2) internal { + assertEq(attestation1.attestationId, attestation2.attestationId); + assertEq(attestation1.schemaId, attestation2.schemaId); + assertEq(attestation1.portal, attestation2.portal); + assertEq(attestation1.subject, attestation2.subject); + assertEq(attestation1.attester, attestation2.attester); + assertEq(attestation1.attestedDate, attestation2.attestedDate); + assertEq(attestation1.expirationDate, attestation2.expirationDate); + assertEq(attestation1.revoked, attestation2.revoked); + assertEq(attestation1.version, attestation2.version); + assertEq(attestation1.attestationData.length, attestation2.attestationData.length); + } +} diff --git a/test/ModuleRegistry.t.sol b/test/ModuleRegistry.t.sol new file mode 100644 index 00000000..723546b4 --- /dev/null +++ b/test/ModuleRegistry.t.sol @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { ModuleRegistry } from "../src/ModuleRegistry.sol"; +import { CorrectModule } from "../src/example/CorrectModule.sol"; +import { IncorrectModule } from "../src/example/IncorrectModule.sol"; +import { PortalRegistryMock } from "./mocks/PortalRegistryMock.sol"; +import { AttestationPayload } from "../src/types/Structs.sol"; +import { Router } from "../src/Router.sol"; + +contract ModuleRegistryTest is Test { + ModuleRegistry private moduleRegistry; + Router public router; + address public portalRegistryAddress; + string private expectedName = "Name"; + string private expectedDescription = "Description"; + address private expectedAddress = address(new CorrectModule()); + address private user = makeAddr("user"); + AttestationPayload private attestationPayload; + + event ModuleRegistered(string name, string description, address moduleAddress); + event Initialized(uint8 version); + + function setUp() public { + router = new Router(); + router.initialize(); + moduleRegistry = new ModuleRegistry(); + router.updateModuleRegistry(address(moduleRegistry)); + vm.prank(address(0)); + moduleRegistry.updateRouter(address(router)); + PortalRegistryMock portalRegistryMock = new PortalRegistryMock(); + portalRegistryAddress = address(portalRegistryMock); + router.updatePortalRegistry(portalRegistryAddress); + portalRegistryMock.setIssuer(user); + + attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + } + + function testAlreadyInitialized() public { + vm.expectRevert("Initializable: contract is already initialized"); + moduleRegistry.initialize(); + } + + function test_updateRouter() public { + ModuleRegistry testModuleRegistry = new ModuleRegistry(); + + vm.prank(address(0)); + testModuleRegistry.updateRouter(address(1)); + address routerAddress = address(testModuleRegistry.router()); + assertEq(routerAddress, address(1)); + } + + function test_updateRouter_InvalidParameter() public { + ModuleRegistry testModuleRegistry = new ModuleRegistry(); + + vm.expectRevert(ModuleRegistry.RouterInvalid.selector); + vm.prank(address(0)); + testModuleRegistry.updateRouter(address(0)); + } + + function testIsContractAddress() public { + // isContractAddress should return false for EOA address + address eoaAddress = vm.addr(1); + bool eoaAddressResult = moduleRegistry.isContractAddress(eoaAddress); + assertEq(eoaAddressResult, false); + + // isContractAddress should return true for contract address + address contractAddress = expectedAddress; + bool contractAddressResult = moduleRegistry.isContractAddress(contractAddress); + assertEq(contractAddressResult, true); + } + + function testRegisterModule() public { + vm.expectEmit(); + emit ModuleRegistered(expectedName, expectedDescription, expectedAddress); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + + (address moduleAddress, string memory name, string memory description) = moduleRegistry.modules(expectedAddress); + assertEq(moduleAddress, expectedAddress); + assertEq(name, expectedName); + assertEq(description, expectedDescription); + } + + function testCannotRegisterModuleWithInvalidIssuer() public { + vm.expectRevert(ModuleRegistry.OnlyIssuer.selector); + vm.startPrank(makeAddr("InvalidIssuer")); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + vm.stopPrank(); + } + + function testCannotRegisterModuleWithoutName() public { + vm.expectRevert(ModuleRegistry.ModuleNameMissing.selector); + vm.prank(user); + moduleRegistry.register("", expectedDescription, expectedAddress); + } + + function testCannotRegisterModuleWithInvalidModuleAddress() public { + vm.expectRevert(ModuleRegistry.ModuleAddressInvalid.selector); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, vm.addr(1)); //vm.addr(1) gives EOA address + } + + function testCannotRegisterModuleWhichHasNotImplementedAbstractModule() public { + IncorrectModule incorrectModule = new IncorrectModule(); + vm.expectRevert(ModuleRegistry.ModuleInvalid.selector); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, address(incorrectModule)); + } + + function testCannotRegisterModuleTwice() public { + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + vm.expectRevert(ModuleRegistry.ModuleAlreadyExists.selector); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + } + + function testStoreModuleAddress() public { + uint256 modulesNumber = moduleRegistry.getModulesNumber(); + assertEq(modulesNumber, 0); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + + modulesNumber = moduleRegistry.getModulesNumber(); + assertEq(modulesNumber, 1); + } + + function testRunModules() public { + // Register 2 modules + address[] memory moduleAddresses = new address[](2); + moduleAddresses[0] = address(new CorrectModule()); + moduleAddresses[1] = address(new CorrectModule()); + vm.startPrank(user); + moduleRegistry.register("Module1", "Description1", moduleAddresses[0]); + moduleRegistry.register("Module2", "Description2", moduleAddresses[1]); + vm.stopPrank(); + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + } + + function testRunModulesWithIncorrectNumberOfValidationPayload() public { + // Register 2 modules + address[] memory moduleAddresses = new address[](2); + moduleAddresses[0] = address(new CorrectModule()); + moduleAddresses[1] = address(new CorrectModule()); + vm.startPrank(user); + moduleRegistry.register("Module1", "Description1", moduleAddresses[0]); + moduleRegistry.register("Module2", "Description2", moduleAddresses[1]); + vm.stopPrank(); + + // Create validation payload + bytes[] memory validationPayload = new bytes[](1); + + vm.expectRevert(ModuleRegistry.ModuleValidationPayloadMismatch.selector); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + } + + function testRunModulesWithoutSendingModuleAddresses() public { + // Register a module + address[] memory moduleAddresses = new address[](0); + + // Create validation payload + bytes[] memory validationPayload = new bytes[](0); + + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + } + + function testRunModulesForUnregisteredModules() public { + // Create 2 modules without registration + address[] memory moduleAddresses = new address[](2); + moduleAddresses[0] = address(new CorrectModule()); + moduleAddresses[1] = address(new CorrectModule()); + + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + + // execute runModules + vm.expectRevert(ModuleRegistry.ModuleNotRegistered.selector); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + } + + function testBulkRunModules() public { + // Register 2 modules + address[] memory moduleAddresses = new address[](2); + moduleAddresses[0] = address(new CorrectModule()); + moduleAddresses[1] = address(new CorrectModule()); + vm.startPrank(user); + moduleRegistry.register("Module1", "Description1", moduleAddresses[0]); + moduleRegistry.register("Module2", "Description2", moduleAddresses[1]); + + // Create validation payloads + bytes[] memory validationPayload1 = new bytes[](2); + bytes[] memory validationPayload2 = new bytes[](2); + + bytes[][] memory validationPayloads = new bytes[][](2); + validationPayloads[0] = validationPayload1; + validationPayloads[1] = validationPayload2; + + AttestationPayload[] memory attestationPayloads = new AttestationPayload[](2); + attestationPayloads[0] = attestationPayload; + attestationPayloads[1] = attestationPayload; + + moduleRegistry.bulkRunModules(moduleAddresses, attestationPayloads, validationPayloads); + vm.stopPrank(); + } + + function testGetModuleAddress() public { + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + + address moduleAddress = moduleRegistry.moduleAddresses(0); + assertEq(moduleAddress, expectedAddress); + } + + function testIsModuleRegistered() public { + bool isRegistered = moduleRegistry.isRegistered(expectedAddress); + assertFalse(isRegistered); + vm.prank(user); + moduleRegistry.register(expectedName, expectedDescription, expectedAddress); + isRegistered = moduleRegistry.isRegistered(expectedAddress); + assertTrue(isRegistered); + } +} diff --git a/test/PortalRegistry.t.sol b/test/PortalRegistry.t.sol new file mode 100644 index 00000000..6f1cfc53 --- /dev/null +++ b/test/PortalRegistry.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { PortalRegistry } from "../src/PortalRegistry.sol"; +import { CorrectModule } from "../src/example/CorrectModule.sol"; +import { Portal } from "../src/types/Structs.sol"; +import { Router } from "../src/Router.sol"; +import { AttestationRegistryMock } from "./mocks/AttestationRegistryMock.sol"; +import { ModuleRegistryMock } from "./mocks/ModuleRegistryMock.sol"; +import { ValidPortalMock } from "./mocks/ValidPortalMock.sol"; +import { InvalidPortalMock } from "./mocks/InvalidPortalMock.sol"; + +contract PortalRegistryTest is Test { + address public user = makeAddr("user"); + Router public router; + PortalRegistry public portalRegistry; + address public moduleRegistryAddress; + address public attestationRegistryAddress; + string public expectedName = "Name"; + string public expectedDescription = "Description"; + string public expectedOwnerName = "Owner Name"; + ValidPortalMock public validPortalMock; + InvalidPortalMock public invalidPortalMock = new InvalidPortalMock(); + + event Initialized(uint8 version); + event PortalRegistered(string name, string description, address portalAddress); + + function setUp() public { + router = new Router(); + router.initialize(); + + portalRegistry = new PortalRegistry(); + router.updatePortalRegistry(address(portalRegistry)); + + moduleRegistryAddress = address(new ModuleRegistryMock()); + attestationRegistryAddress = address(new AttestationRegistryMock()); + vm.prank(address(0)); + portalRegistry.updateRouter(address(router)); + + router.updateModuleRegistry(moduleRegistryAddress); + router.updateAttestationRegistry(attestationRegistryAddress); + vm.prank(address(0)); + portalRegistry.setIssuer(user); + + validPortalMock = new ValidPortalMock(); + } + + function test_alreadyInitialized() public { + vm.expectRevert("Initializable: contract is already initialized"); + portalRegistry.initialize(); + } + + function test_updateRouter() public { + PortalRegistry testPortalRegistry = new PortalRegistry(); + + vm.prank(address(0)); + testPortalRegistry.updateRouter(address(1)); + address routerAddress = address(testPortalRegistry.router()); + assertEq(routerAddress, address(1)); + } + + function test_updateRouter_InvalidParameter() public { + PortalRegistry testPortalRegistry = new PortalRegistry(); + + vm.expectRevert(PortalRegistry.RouterInvalid.selector); + vm.prank(address(0)); + testPortalRegistry.updateRouter(address(0)); + } + + function test_setIssuer_isIssuer_removeIssuer() public { + vm.startPrank(address(0)); + address issuerAddress = makeAddr("Issuer"); + portalRegistry.setIssuer(issuerAddress); + + bool isIssuer = portalRegistry.isIssuer(issuerAddress); + assertEq(isIssuer, true); + + portalRegistry.removeIssuer(issuerAddress); + bool isIssuerAfterRemoval = portalRegistry.isIssuer(issuerAddress); + assertEq(isIssuerAfterRemoval, false); + vm.stopPrank(); + } + + function test_register() public { + vm.expectEmit(); + emit PortalRegistered(expectedName, expectedDescription, address(validPortalMock)); + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + + uint256 portalCount = portalRegistry.getPortalsCount(); + assertEq(portalCount, 1); + + Portal memory expectedPortal = Portal( + address(validPortalMock), + user, + new address[](0), + true, + expectedName, + expectedDescription, + expectedOwnerName + ); + + Portal memory registeredPortal = portalRegistry.getPortalByAddress(address(validPortalMock)); + _assertPortal(registeredPortal, expectedPortal); + } + + function test_register_OnlyIssuer() public { + vm.expectRevert(PortalRegistry.OnlyIssuer.selector); + vm.prank(makeAddr("InvalidIssuer")); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_register_PortalAlreadyExists() public { + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + vm.expectRevert(PortalRegistry.PortalAlreadyExists.selector); + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_register_PortalAddressInvalid() public { + vm.expectRevert(PortalRegistry.PortalAddressInvalid.selector); + vm.prank(user); + portalRegistry.register(address(0), expectedName, expectedDescription, true, expectedOwnerName); + + vm.expectRevert(PortalRegistry.PortalAddressInvalid.selector); + vm.prank(user); + portalRegistry.register(user, expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_register_PortalNameMissing() public { + vm.expectRevert(PortalRegistry.PortalNameMissing.selector); + vm.prank(user); + portalRegistry.register(address(validPortalMock), "", expectedDescription, true, expectedOwnerName); + } + + function test_register_PortalDescriptionMissing() public { + vm.expectRevert(PortalRegistry.PortalDescriptionMissing.selector); + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, "", true, expectedOwnerName); + } + + function test_register_PortalOwnerNameMissing() public { + vm.expectRevert(PortalRegistry.PortalOwnerNameMissing.selector); + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, ""); + } + + function test_register_PortalInvalid() public { + vm.expectRevert(PortalRegistry.PortalInvalid.selector); + vm.prank(user); + portalRegistry.register(address(invalidPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_deployDefaultPortal() public { + CorrectModule correctModule = new CorrectModule(); + address[] memory modules = new address[](1); + modules[0] = address(correctModule); + vm.prank(user); + portalRegistry.deployDefaultPortal(modules, expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_deployDefaultPortal_OnlyIssuer() public { + CorrectModule correctModule = new CorrectModule(); + address[] memory modules = new address[](1); + modules[0] = address(correctModule); + vm.expectRevert(PortalRegistry.OnlyIssuer.selector); + vm.prank(makeAddr("InvalidIssuer")); + portalRegistry.deployDefaultPortal(modules, expectedName, expectedDescription, true, expectedOwnerName); + } + + function test_getPortals_PortalNotRegistered() public { + vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); + portalRegistry.getPortalByAddress(address(validPortalMock)); + } + + function test_isRegistered() public { + assertEq(portalRegistry.isRegistered(address(validPortalMock)), false); + vm.prank(user); + portalRegistry.register(address(validPortalMock), expectedName, expectedDescription, true, expectedOwnerName); + assertEq(portalRegistry.isRegistered(address(validPortalMock)), true); + } + + function _assertPortal(Portal memory portal1, Portal memory portal2) internal { + assertEq(portal1.name, portal2.name); + assertEq(portal1.description, portal2.description); + assertEq(portal1.isRevocable, portal2.isRevocable); + assertEq(portal1.ownerAddress, portal2.ownerAddress); + assertEq(portal1.ownerName, portal2.ownerName); + } +} diff --git a/test/Router.t.sol b/test/Router.t.sol new file mode 100644 index 00000000..268e8d32 --- /dev/null +++ b/test/Router.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { Router } from "../src/Router.sol"; + +contract RouterTest is Test { + Router public router; + address public attestationRegistry = makeAddr("attestationRegistry"); + address public moduleRegistry = makeAddr("moduleRegistry"); + address public portalRegistry = makeAddr("portalRegistry"); + address public schemaRegistry = makeAddr("schemaRegistry"); + address public user = makeAddr("user"); + + event Initialized(uint8 version); + event AttestationRegistryUpdated(address indexed registryAddress); + event ModuleRegistryUpdated(address indexed registryAddress); + event PortalRegistryUpdated(address indexed registryAddress); + event SchemaRegistryUpdated(address indexed registryAddress); + + function setUp() public { + router = new Router(); + router.initialize(); + } + + function testInitialize() public { + vm.expectEmit(); + emit Initialized(1); + Router testRouter = new Router(); + testRouter.initialize(); + vm.expectRevert("Initializable: contract is already initialized"); + testRouter.initialize(); + } + + function testUpdateAttestationRegistry() public { + vm.expectEmit(); + emit AttestationRegistryUpdated(attestationRegistry); + router.updateAttestationRegistry(attestationRegistry); + assertEq(router.getAttestationRegistry(), attestationRegistry); + } + + function testUpdateAttestationRegistryNotOwner() public { + vm.prank(user); + vm.expectRevert("Ownable: caller is not the owner"); + router.updateAttestationRegistry(attestationRegistry); + } + + function testUpdateModuleRegistry() public { + vm.expectEmit(); + emit ModuleRegistryUpdated(moduleRegistry); + router.updateModuleRegistry(moduleRegistry); + assertEq(router.getModuleRegistry(), moduleRegistry); + } + + function testUpdateModuleRegistryNotOwner() public { + vm.prank(user); + vm.expectRevert("Ownable: caller is not the owner"); + router.updateModuleRegistry(moduleRegistry); + } + + function testUpdatePortalRegistry() public { + vm.expectEmit(); + emit PortalRegistryUpdated(portalRegistry); + router.updatePortalRegistry(portalRegistry); + assertEq(router.getPortalRegistry(), portalRegistry); + } + + function testUpdatePortalRegistryNotOwner() public { + vm.prank(user); + vm.expectRevert("Ownable: caller is not the owner"); + router.updatePortalRegistry(portalRegistry); + } + + function testUpdateSchemaRegistry() public { + vm.expectEmit(); + emit SchemaRegistryUpdated(schemaRegistry); + router.updateSchemaRegistry(schemaRegistry); + assertEq(router.getSchemaRegistry(), schemaRegistry); + } + + function testUpdateSchemaRegistryNotOwner() public { + vm.prank(user); + vm.expectRevert("Ownable: caller is not the owner"); + router.updateSchemaRegistry(schemaRegistry); + } +} diff --git a/test/SchemaRegistry.t.sol b/test/SchemaRegistry.t.sol new file mode 100644 index 00000000..5a8ed7cf --- /dev/null +++ b/test/SchemaRegistry.t.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { SchemaRegistry } from "../src/SchemaRegistry.sol"; +import { PortalRegistryMock } from "./mocks/PortalRegistryMock.sol"; +import { Schema } from "../src/types/Structs.sol"; +import { Router } from "../src/Router.sol"; + +contract SchemaRegistryTest is Test { + SchemaRegistry private schemaRegistry; + Router public router; + address public portalRegistryAddress; + bytes32 private expectedId = 0x36304af55bbea73214675d3770f679b4b6e0bfff512f5af01046e6f5d29261e3; + string private expectedName = "Name"; + string private expectedDescription = "Description"; + string private expectedContext = "Context"; + string private expectedString = "this is a schema"; + address private user = makeAddr("user"); + + event SchemaCreated(bytes32 indexed id, string name, string description, string context, string schemaString); + event Initialized(uint8 version); + + function setUp() public { + router = new Router(); + router.initialize(); + schemaRegistry = new SchemaRegistry(); + router.updateSchemaRegistry(address(schemaRegistry)); + vm.prank(address(0)); + schemaRegistry.updateRouter(address(router)); + PortalRegistryMock portalRegistryMock = new PortalRegistryMock(); + portalRegistryAddress = address(portalRegistryMock); + router.updatePortalRegistry(portalRegistryAddress); + portalRegistryMock.setIssuer(user); + } + + function testAlreadyInitialized() public { + vm.expectRevert("Initializable: contract is already initialized"); + schemaRegistry.initialize(); + } + + function test_updateRouter() public { + SchemaRegistry testSchemaRegistry = new SchemaRegistry(); + + vm.prank(address(0)); + testSchemaRegistry.updateRouter(address(1)); + address routerAddress = address(testSchemaRegistry.router()); + assertEq(routerAddress, address(1)); + } + + function test_updateRouter_InvalidParameter() public { + SchemaRegistry testSchemaRegistry = new SchemaRegistry(); + + vm.expectRevert(SchemaRegistry.RouterInvalid.selector); + vm.prank(address(0)); + testSchemaRegistry.updateRouter(address(0)); + } + + function testGetIdFromSchemaString() public { + bytes32 id = schemaRegistry.getIdFromSchemaString(expectedString); + assertEq(id, expectedId); + } + + function testCreateSchema() public { + vm.expectEmit(); + emit SchemaCreated(expectedId, expectedName, expectedDescription, expectedContext, expectedString); + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + + Schema memory expectedSchema = Schema(expectedName, expectedDescription, expectedContext, expectedString); + + Schema memory registeredSchema = schemaRegistry.getSchema(expectedId); + _assertSchema(registeredSchema, expectedSchema); + vm.stopPrank(); + } + + function testCannotCreateSchemaWithInvalidIssuer() public { + vm.expectRevert(SchemaRegistry.OnlyIssuer.selector); + vm.startPrank(makeAddr("InvalidIssuer")); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + vm.stopPrank(); + } + + function testCannotCreateSchemaWithoutName() public { + vm.expectRevert(SchemaRegistry.SchemaNameMissing.selector); + vm.prank(user); + schemaRegistry.createSchema("", expectedDescription, expectedContext, expectedString); + } + + function testCannotCreateSchemaWithoutString() public { + vm.expectRevert(SchemaRegistry.SchemaStringMissing.selector); + vm.prank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, ""); + } + + function testCannotCreateSchemaWithoutContext() public { + vm.expectRevert(SchemaRegistry.SchemaContextMissing.selector); + vm.prank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, "", expectedString); + } + + function testCannotCreateSchemaTwice() public { + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + vm.expectRevert(SchemaRegistry.SchemaAlreadyExists.selector); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + vm.stopPrank(); + } + + function testGetSchema() public { + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + + Schema memory expectedSchema = Schema(expectedName, expectedDescription, expectedContext, expectedString); + + Schema memory registeredSchema = schemaRegistry.getSchema(expectedId); + _assertSchema(registeredSchema, expectedSchema); + vm.stopPrank(); + } + + function testGetSchemaNotRegistered() public { + vm.expectRevert(SchemaRegistry.SchemaNotRegistered.selector); + schemaRegistry.getSchema(bytes32("not registered")); + } + + function testStoreSchemaId() public { + uint256 schemasNumber = schemaRegistry.getSchemasNumber(); + assertEq(schemasNumber, 0); + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + + schemasNumber = schemaRegistry.getSchemasNumber(); + assertEq(schemasNumber, 1); + vm.stopPrank(); + } + + function testGetSchemaId() public { + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + + bytes32 schemaId = schemaRegistry.schemaIds(0); + assertEq(schemaId, expectedId); + vm.stopPrank(); + } + + function testIsSchemaRegistered() public { + bool isRegistered = schemaRegistry.isRegistered(expectedId); + assertFalse(isRegistered); + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + isRegistered = schemaRegistry.isRegistered(expectedId); + assertTrue(isRegistered); + vm.stopPrank(); + } + + function _assertSchema(Schema memory schema1, Schema memory schema2) internal { + assertEq(schema2.name, schema1.name); + assertEq(schema2.description, schema1.description); + assertEq(schema2.context, schema1.context); + assertEq(schema2.schema, schema1.schema); + } +} diff --git a/test/example/EASPortal.t.sol b/test/example/EASPortal.t.sol new file mode 100644 index 00000000..21ec593a --- /dev/null +++ b/test/example/EASPortal.t.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { EASPortal } from "../../src/example/EASPortal.sol"; +import { Router } from "../../src/Router.sol"; +import { AbstractPortal } from "../../src/interface/AbstractPortal.sol"; +import { AttestationRegistryMock } from "../mocks/AttestationRegistryMock.sol"; +import { ModuleRegistryMock } from "../mocks/ModuleRegistryMock.sol"; +import { ERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol"; + +contract EASPortalTest is Test { + address public attester = makeAddr("attester"); + EASPortal public easPortal; + address[] public modules = new address[](0); + ModuleRegistryMock public moduleRegistryMock = new ModuleRegistryMock(); + AttestationRegistryMock public attestationRegistryMock = new AttestationRegistryMock(); + Router public router = new Router(); + + event Initialized(uint8 version); + event AttestationRegistered(); + event BulkAttestationsRegistered(); + + function setUp() public { + easPortal = new EASPortal(); + router.initialize(); + router.updateModuleRegistry(address(moduleRegistryMock)); + router.updateAttestationRegistry(address(attestationRegistryMock)); + easPortal.initialize(modules, address(router)); + } + + function test_initialize() public { + vm.expectRevert("Initializable: contract is already initialized"); + easPortal.initialize(modules, address(router)); + } + + function test_attest() public { + // Create EAS attestation request + EASPortal.AttestationRequestData memory attestationRequestData = EASPortal.AttestationRequestData( + makeAddr("recipient"), + uint64(block.timestamp + 1 days), + false, + bytes32("refUID"), + new bytes(0), + uint256(1) + ); + EASPortal.AttestationRequest memory attestationRequest = EASPortal.AttestationRequest( + bytes32(uint256(1)), + attestationRequestData + ); + + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + easPortal.attest(attestationRequest); + } + + function test_bulkAttest() public { + // Create EAS attestation request + EASPortal.AttestationRequestData memory attestationRequestData = EASPortal.AttestationRequestData( + makeAddr("recipient"), + uint64(block.timestamp + 1 days), + false, + bytes32("refUID"), + new bytes(0), + uint256(1) + ); + + EASPortal.AttestationRequest[] memory attestationsRequests = new EASPortal.AttestationRequest[](2); + attestationsRequests[0] = EASPortal.AttestationRequest(bytes32(uint256(1)), attestationRequestData); + attestationsRequests[1] = EASPortal.AttestationRequest(bytes32(uint256(1)), attestationRequestData); + + vm.expectEmit(true, true, true, true); + emit BulkAttestationsRegistered(); + easPortal.bulkAttest(attestationsRequests); + } + + function test_revoke() public { + vm.expectRevert(EASPortal.NoRevocation.selector); + easPortal.revoke(bytes32(uint256(1)), bytes32(uint256(1))); + } + + function test_bulkRevoke() public { + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = bytes32(uint256(1)); + attestationsToRevoke[1] = bytes32(uint256(2)); + + bytes32[] memory replacingAttestations = new bytes32[](2); + replacingAttestations[0] = bytes32(uint256(0)); + replacingAttestations[1] = bytes32(uint256(3)); + + vm.expectRevert(EASPortal.NoBulkRevocation.selector); + easPortal.bulkRevoke(attestationsToRevoke, replacingAttestations); + } + + function testSupportsInterface() public { + bool isIERC165Supported = easPortal.supportsInterface(type(ERC165Upgradeable).interfaceId); + assertEq(isIERC165Supported, true); + bool isEASAbstractPortalSupported = easPortal.supportsInterface(type(AbstractPortal).interfaceId); + assertEq(isEASAbstractPortalSupported, true); + } + + function test_getAttester() public { + vm.prank(attester); + address registeredAttester = easPortal._getAttester(); + assertEq(registeredAttester, attester); + } +} diff --git a/test/example/MsgSenderModule.t.sol b/test/example/MsgSenderModule.t.sol new file mode 100644 index 00000000..b6d30149 --- /dev/null +++ b/test/example/MsgSenderModule.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { AbstractModule } from "../../src/interface/AbstractModule.sol"; +import { MsgSenderModule } from "../../src/example/MsgSenderModule.sol"; +import { AttestationPayload } from "../../src/types/Structs.sol"; +// solhint-disable-next-line max-line-length +import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; + +contract MsgSenderModuleTest is Test { + MsgSenderModule private msgSenderModule; + address private expectedMsgSender = 0x809e815596AbEB3764aBf81BE2DC39fBBAcc9949; + AttestationPayload private attestationPayload; + + event ModuleRegistered(string name, string description, address moduleAddress); + event Initialized(uint8 version); + + function setUp() public { + msgSenderModule = new MsgSenderModule(); + msgSenderModule.initialize(expectedMsgSender); + + attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + } + + function testInitialize() public { + msgSenderModule = new MsgSenderModule(); + vm.expectEmit(); + emit Initialized(1); + msgSenderModule.initialize(expectedMsgSender); + assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); + } + + function testCorrectMsgSenderAddress() public { + assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); + bytes[] memory validationPayload = new bytes[](0); + address msgSender = expectedMsgSender; + + bytes[] memory _validationPayload = msgSenderModule.run(attestationPayload, validationPayload, msgSender); + + assertBytesArrayEq(_validationPayload, validationPayload); + } + + function testIncorrectMsgSenderAddress() public { + assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); + bytes[] memory validationPayload = new bytes[](0); + address incorrectMsgSender = address(1); + vm.expectRevert(MsgSenderModule.WrongTransactionSender.selector); + msgSenderModule.run(attestationPayload, validationPayload, incorrectMsgSender); + } + + function testSupportsInterface() public { + bool isIERC165Supported = msgSenderModule.supportsInterface(type(IERC165Upgradeable).interfaceId); + assertEq(isIERC165Supported, true); + bool isAbstractModuleSupported = msgSenderModule.supportsInterface(type(AbstractModule).interfaceId); + assertEq(isAbstractModuleSupported, true); + } + + function assertBytesArrayEq(bytes[] memory actualBytesArray, bytes[] memory expectedBytesArray) public { + // Compare bytes[] arrays using assertEq + require(expectedBytesArray.length == actualBytesArray.length, "Number of elements are not equal"); + + for (uint256 i = 0; i < expectedBytesArray.length; i++) { + assertEq(expectedBytesArray[i], actualBytesArray[i]); + } + } +} diff --git a/test/mocks/AttestationRegistryMock.sol b/test/mocks/AttestationRegistryMock.sol new file mode 100644 index 00000000..608ab4da --- /dev/null +++ b/test/mocks/AttestationRegistryMock.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AttestationPayload, Attestation } from "../../src/types/Structs.sol"; + +contract AttestationRegistryMock { + uint16 public version; + uint32 private attestationIdCounter; + mapping(bytes32 attestationId => Attestation attestation) private attestations; + + event AttestationRegistered(); + event BulkAttestationsRegistered(); + event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + + function test() public {} + + function attest(AttestationPayload calldata attestationPayload, address attester) public { + require(bytes32(attestationPayload.schemaId) != 0, "Invalid attestationPayload"); + require(attester != address(0), "Invalid attester"); + + attestationIdCounter++; + // Create attestation + Attestation memory attestation = Attestation( + bytes32(abi.encode(attestationIdCounter)), + attestationPayload.schemaId, + bytes32(0), + attester, + msg.sender, + uint64(block.timestamp), + attestationPayload.expirationDate, + 0, + version, + false, + attestationPayload.subject, + attestationPayload.attestationData + ); + attestations[attestation.attestationId] = attestation; + + emit AttestationRegistered(); + } + + function bulkAttest(AttestationPayload[] calldata attestationsPayloads, address attester) public { + require(attestationsPayloads.length > 0, "Invalid attestationsPayloads"); + require(attester != address(0), "Invalid attester"); + emit BulkAttestationsRegistered(); + } + + function revoke(bytes32 attestationId, bytes32 replacedBy) public { + require(bytes32(attestationId) != 0, "Invalid attestation"); + emit AttestationRevoked(attestationId, replacedBy); + } + + function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public { + require(attestationIds.length > 0, "Invalid attestation"); + emit BulkAttestationsRevoked(attestationIds, replacedBy); + } + + function getVersionNumber() public view returns (uint16) { + return version; + } + + function getAttestation(bytes32 attestationId) public view returns (Attestation memory) { + return attestations[attestationId]; + } +} diff --git a/test/mocks/InvalidPortalMock.sol b/test/mocks/InvalidPortalMock.sol new file mode 100644 index 00000000..059d657a --- /dev/null +++ b/test/mocks/InvalidPortalMock.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +contract InvalidPortalMock { + function test() public {} +} diff --git a/test/mocks/ModuleRegistryMock.sol b/test/mocks/ModuleRegistryMock.sol new file mode 100644 index 00000000..9a9183fc --- /dev/null +++ b/test/mocks/ModuleRegistryMock.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AttestationPayload } from "../../src/types/Structs.sol"; + +contract ModuleRegistryMock { + event ModulesRunForAttestation(); + event ModulesBulkRunForAttestation(); + + function test() public {} + + function runModules( + address[] memory modulesAddresses, + AttestationPayload memory attestationPayload, + bytes[] memory validationPayload + ) public {} + + function bulkRunModules( + address[] memory modulesAddresses, + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) public { + require(modulesAddresses.length >= 0, "Invalid modulesAddresses"); + require(attestationsPayloads.length >= 0, "Invalid attestationsPayloads"); + require(validationPayloads.length >= 0, "Invalid validationPayloads"); + emit ModulesBulkRunForAttestation(); + } +} diff --git a/test/mocks/PortalRegistryMock.sol b/test/mocks/PortalRegistryMock.sol new file mode 100644 index 00000000..f342cd38 --- /dev/null +++ b/test/mocks/PortalRegistryMock.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Portal } from "../../src/types/Structs.sol"; + +contract PortalRegistryMock { + event PortalRegistered(string name, string description, address portalAddress); + + mapping(address id => Portal portal) private portals; + + mapping(address issuerAddress => bool isIssuer) private issuers; + + function test() public {} + + function register( + address id, + string memory name, + string memory description, + bool isRevocable, + string memory ownerName + ) external { + Portal memory newPortal = Portal(id, msg.sender, new address[](0), isRevocable, name, description, ownerName); + portals[id] = newPortal; + emit PortalRegistered(name, description, id); + } + + function isRegistered(address id) public view returns (bool) { + return portals[id].id != address(0); + } + + function getPortalByAddress(address id) public view returns (Portal memory) { + return portals[id]; + } + + function setIssuer(address issuer) public { + issuers[issuer] = true; + } + + /** + * @notice Checks if a given address is an issuer + * @return A flag indicating whether the given address is an issuer + */ + function isIssuer(address issuer) public view returns (bool) { + return issuers[issuer]; + } +} diff --git a/test/mocks/SchemaRegistryMock.sol b/test/mocks/SchemaRegistryMock.sol new file mode 100644 index 00000000..d2582427 --- /dev/null +++ b/test/mocks/SchemaRegistryMock.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +contract SchemaRegistryMock { + mapping(bytes32 id => bool exists) public schemas; + + event SchemaCreated(bytes32 indexed id, string name, string description, string context, string schemaString); + + function test() public {} + + function getIdFromSchemaString(string memory schema) public pure returns (bytes32) { + return keccak256(abi.encodePacked(schema)); + } + + function createSchema( + string memory name, + string memory description, + string memory context, + string memory schemaString + ) public { + bytes32 schemaId = getIdFromSchemaString(schemaString); + schemas[schemaId] = true; + emit SchemaCreated(schemaId, name, description, context, schemaString); + } + + function isRegistered(bytes32 schemaId) public view returns (bool) { + return schemas[schemaId]; + } +} diff --git a/test/mocks/ValidPortalMock.sol b/test/mocks/ValidPortalMock.sol new file mode 100644 index 00000000..2dd84ca4 --- /dev/null +++ b/test/mocks/ValidPortalMock.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractPortal } from "../../src/interface/AbstractPortal.sol"; +import { AttestationPayload } from "../../src/types/Structs.sol"; + +contract ValidPortalMock is AbstractPortal { + function test() public {} + + function _beforeAttest(AttestationPayload memory attestationPayload, uint256 value) internal override {} + + function _afterAttest() internal override {} + + function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} + + function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} + + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal override {} + + function _getAttester() public view override returns (address) { + return msg.sender; + } +} diff --git a/test/portal/DefaultPortal.t.sol b/test/portal/DefaultPortal.t.sol new file mode 100644 index 00000000..c5048ab1 --- /dev/null +++ b/test/portal/DefaultPortal.t.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Vm } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { AbstractPortal } from "../../src/interface/AbstractPortal.sol"; +import { DefaultPortal } from "../../src/portal/DefaultPortal.sol"; +import { AttestationPayload } from "../../src/types/Structs.sol"; +import { CorrectModule } from "../../src/example/CorrectModule.sol"; +import { AttestationRegistryMock } from "../mocks/AttestationRegistryMock.sol"; +import { ModuleRegistryMock } from "../mocks/ModuleRegistryMock.sol"; +import { PortalRegistryMock } from "../mocks/PortalRegistryMock.sol"; +import { ERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol"; +import { Router } from "../../src/Router.sol"; + +contract DefaultPortalTest is Test { + CorrectModule public correctModule = new CorrectModule(); + address[] public modules = new address[](1); + DefaultPortal public defaultPortal; + ModuleRegistryMock public moduleRegistryMock = new ModuleRegistryMock(); + PortalRegistryMock public portalRegistryMock = new PortalRegistryMock(); + AttestationRegistryMock public attestationRegistryMock = new AttestationRegistryMock(); + Router public router = new Router(); + address public portalOwner = makeAddr("portalOwner"); + + event Initialized(uint8 version); + event PortalRegistered(string name, string description, address portalAddress); + event AttestationRegistered(); + event BulkAttestationsRegistered(); + event ModulesRunForAttestation(); + event ModulesBulkRunForAttestation(); + event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + + function setUp() public { + modules.push(address(correctModule)); + defaultPortal = new DefaultPortal(); + router.initialize(); + router.updateModuleRegistry(address(moduleRegistryMock)); + router.updateAttestationRegistry(address(attestationRegistryMock)); + router.updatePortalRegistry(address(portalRegistryMock)); + + vm.prank(portalOwner); + portalRegistryMock.register(address(defaultPortal), "Name", "Description", true, "Owner name"); + + defaultPortal.initialize(modules, address(router)); + } + + function test_setup() public { + assertEq(address(defaultPortal.modules(0)), address(modules[0])); + assertEq(address(defaultPortal.moduleRegistry()), address(moduleRegistryMock)); + assertEq(address(defaultPortal.attestationRegistry()), address(attestationRegistryMock)); + assertEq(address(defaultPortal.portalRegistry()), address(portalRegistryMock)); + assertEq(portalRegistryMock.getPortalByAddress(address(defaultPortal)).ownerAddress, portalOwner); + } + + function test_initialize() public { + DefaultPortal defaultPortalTest = new DefaultPortal(); + vm.expectEmit(); + emit Initialized(1); + defaultPortalTest.initialize(modules, address(router)); + + vm.expectRevert("Initializable: contract is already initialized"); + defaultPortalTest.initialize(modules, address(router)); + } + + function test_getModules() public { + address[] memory _modules = defaultPortal.getModules(); + assertEq(_modules, modules); + } + + function test_attest() public { + // Create attestation payload + AttestationPayload memory attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + defaultPortal.attest(attestationPayload, validationPayload); + } + + function test_bulkAttest(AttestationPayload[2] memory attestationsPayloads) public { + vm.assume(bytes32(attestationsPayloads[0].schemaId) != 0); + vm.assume(bytes32(attestationsPayloads[1].schemaId) != 0); + // Create attestations payloads + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationsPayloads[0]; + payloadsToAttest[1] = attestationsPayloads[1]; + + // Create validation payloads + bytes[] memory validationPayload1 = new bytes[](1); + bytes[] memory validationPayload2 = new bytes[](1); + + bytes[][] memory validationPayloads = new bytes[][](2); + validationPayloads[0] = validationPayload1; + validationPayloads[1] = validationPayload2; + + vm.expectEmit(true, true, true, true); + emit ModulesBulkRunForAttestation(); + vm.expectEmit(true, true, true, true); + emit BulkAttestationsRegistered(); + defaultPortal.bulkAttest(payloadsToAttest, validationPayloads); + } + + function test_revoke_byPortalOwner() public { + // Create attestation payload + AttestationPayload memory attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + + // Do register the attestation + vm.prank(makeAddr("attester")); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + defaultPortal.attest(attestationPayload, validationPayload); + + // Revoke the attestation as portal owner + vm.prank(portalOwner); + vm.expectEmit(true, true, true, true); + emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(0)); + defaultPortal.revoke(bytes32(abi.encode(1)), ""); + } + + function test_revokeFail_OnlyOwner() public { + // Create attestation payload + AttestationPayload memory attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + + // Do register the attestation + vm.prank(makeAddr("attester")); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + defaultPortal.attest(attestationPayload, validationPayload); + + // Revoke the attestation as a random user + vm.prank(makeAddr("random")); + vm.expectRevert(AbstractPortal.OnlyPortalOwner.selector); + defaultPortal.revoke(bytes32(abi.encode(1)), ""); + } + + function test_bulkRevoke() public { + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = bytes32("1"); + attestationsToRevoke[1] = bytes32("2"); + bytes32[] memory replacingAttestations = new bytes32[](2); + replacingAttestations[0] = bytes32(0); + replacingAttestations[1] = bytes32(0); + + vm.expectEmit(true, true, true, true); + emit BulkAttestationsRevoked(attestationsToRevoke, replacingAttestations); + defaultPortal.bulkRevoke(attestationsToRevoke, replacingAttestations); + } + + function testSupportsInterface() public { + bool isIERC165Supported = defaultPortal.supportsInterface(type(ERC165Upgradeable).interfaceId); + assertEq(isIERC165Supported, true); + bool isAbstractPortalSupported = defaultPortal.supportsInterface(type(AbstractPortal).interfaceId); + assertEq(isAbstractPortalSupported, true); + } + + function test_getAttester() public { + address attester = makeAddr("attester"); + vm.prank(attester); + address registeredAttester = defaultPortal._getAttester(); + assertEq(registeredAttester, attester); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..574e785c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +}