From 72c2c154bb2f1bc3b679703dc93cbe96c23e834f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAkira-Taniguchi=E2=80=9D?= <“dededededaiou2003@yahoo.co.jp”> Date: Mon, 2 Feb 2026 14:31:36 +0900 Subject: [PATCH 1/4] first --- .env.example | 47 ++++----- .github/workflows/test.yml | 46 ++++++++- .solhint.json | 16 +++ .solhintignore | 2 + AGENTS.md | 155 +++++++++++++++++++++++++++++ README.md | 18 ++-- foundry.lock | 8 ++ foundry.toml | 112 +++------------------ package.json | 23 +++++ script/Deploy.s.sol | 3 +- slither.config.json | 4 + src/CREATE3Factory.flattened | 2 +- src/CREATE3Factory.sol | 16 +-- src/ICREATE3Factory.sol | 12 +-- test/CREATE3Factory.t.sol | 183 +++++++++++++++++++++++++++++++++++ 15 files changed, 488 insertions(+), 159 deletions(-) create mode 100644 .solhint.json create mode 100644 .solhintignore create mode 100644 AGENTS.md create mode 100644 foundry.lock create mode 100644 package.json create mode 100644 slither.config.json create mode 100644 test/CREATE3Factory.t.sol diff --git a/.env.example b/.env.example index a623f11..496d381 100644 --- a/.env.example +++ b/.env.example @@ -1,32 +1,23 @@ # Deployment Key -PRIVATE_KEY=XXX +PRIVATE_KEY= -# Network and account info -RPC_URL_MAINNET=XXX -RPC_URL_GOERLI=XXX -RPC_URL_ARBITRUM=XXX -RPC_URL_BERACHAIN=XXX -RPC_URL_OPTIMISM=XXX -RPC_URL_POLYGON=XXX -RPC_URL_AVALANCHE=XXX -RPC_URL_FANTOM=XXX -RPC_URL_ZKEVM=https://zkevm-rpc.com +# RPC URLs - Mainnet +RPC_URL_MAINNET= +RPC_URL_ARBITRUM= +RPC_URL_BASE= +RPC_URL_BSC= +RPC_URL_SCROLL= -# Testnets -RPC_URL_CONSENSYS_ZKEVM_TESTNET=XXX -RPC_URL_BSC_TESTNET=XXX -RPC_URL_SCROLL_ALPHA=https://alpha-rpc.scroll.io/l2 +# RPC URLs - Testnet +RPC_URL_SEPOLIA= +RPC_URL_ARBITRUM_SEPOLIA= +RPC_URL_BASE_SEPOLIA= +RPC_URL_BSC_TESTNET= +RPC_URL_SCROLL_SEPOLIA= -# Block Explorere for verification -ETHERSCAN_KEY=XXX -ARBISCAN_KEY=XXX -BERACHAIN_ETHERSCAN_API_KEY=XXX -POLYGONSCAN_KEY=XXX -OPTIMISM_ETHERSCAN_KEY=XXX -SNOWTRACE_KEY=XXX -FTMSCAN_KEY=XXX -BSCSCAN_KEY=XXX -GNOSISBSCOUT_KEY=XXX -MOONRIVER_MOONSCAN_KEY=XXX -MOONBEAM_MOONSCAN_KEY=XXX -NOVA_ARBISCAN_KEY=XXX +# Block Explorer API Keys +ETHERSCAN_KEY= +ARBISCAN_KEY= +BASESCAN_API_KEY= +BSCSCAN_KEY= +SCROLLSCAN_API_KEY= diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09880b1..b58e72a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,9 @@ name: test -on: workflow_dispatch +on: + push: + pull_request: + workflow_dispatch: env: FOUNDRY_PROFILE: ci @@ -13,10 +16,15 @@ jobs: name: Foundry project runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 with: submodules: recursive + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '18' + - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: @@ -25,10 +33,42 @@ jobs: - name: Run Forge build run: | forge --version - forge build --sizes + forge build id: build + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + + - name: Run Forge lint + run: | + forge lint src test script + id: lint + - name: Run Forge tests run: | forge test -vvv id: test + + - name: Install npm dependencies + run: npm ci + + - name: Run solhint + run: | + yes | npm run lint + id: solhint + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: Install Slither + run: | + pip install slither-analyzer + + - name: Run Slither + run: | + slither src/ + id: slither \ No newline at end of file diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 0000000..bd8ca44 --- /dev/null +++ b/.solhint.json @@ -0,0 +1,16 @@ +{ + "extends": "solhint:recommended", + "rules": { + "import-path-check": "off", + "use-natspec": "off", + "func-visibility": ["warn", {"ignoreConstructors": true}], + "gas-strict-inequalities": "off", + "gas-indexed-events": "off", + "no-console": "off", + "one-contract-per-file": "off", + "no-empty-blocks": "off", + "var-name-mixedcase": "off", + "func-name-mixedcase": "off", + "gas-small-strings": "off" + } +} diff --git a/.solhintignore b/.solhintignore new file mode 100644 index 0000000..28cddc2 --- /dev/null +++ b/.solhintignore @@ -0,0 +1,2 @@ +# Auto-generated verifier contracts +src/verifiers/** diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..eae1a1e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,155 @@ +# AGENTS.md + +This file provides context for AI coding agents working on this project. + +## Project Overview + +This is a CREATE3 Factory contract that enables deterministic contract deployment across multiple EVM chains. Contracts deployed via this factory will have the same address on all supported chains, regardless of constructor arguments. + +## Key Concepts + +### CREATE3 vs CREATE2 vs CREATE + +| Method | Address Depends On | Use Case | +|--------|-------------------|----------| +| CREATE | deployer address + nonce | Standard deployment | +| CREATE2 | deployer + salt + bytecode hash | Deterministic, but bytecode-dependent | +| CREATE3 | factory + salt + caller | Deterministic, bytecode-independent | + +### How This Factory is Deployed + +This factory uses **CREATE2** (not CREATE) for deployment to ensure the same factory address across all chains without nonce synchronization: + +```solidity +// Deploy.s.sol +bytes32 salt = keccak256("intmax"); +factory = new CREATE3Factory{salt: salt}(); +``` + +The factory address is determined by: +- Deployer address (from PRIVATE_KEY) +- Salt ("intmax") +- Factory bytecode + +### Bytecode Determinism + +To ensure identical bytecode across different compilation environments: + +```toml +# foundry.toml +bytecode_hash = "none" +cbor_metadata = false +``` + +These settings disable compiler metadata embedding. + +## Project Structure + +``` +create3-factory/ +├── src/ +│ ├── CREATE3Factory.sol # Main factory contract +│ ├── ICREATE3Factory.sol # Interface +│ └── CREATE3Factory.flattened # Flattened for verification +├── script/ +│ └── Deploy.s.sol # Foundry deployment script +├── deploy/ +│ └── deploy.sh # Shell script wrapper +├── deployments/ # Deployment records (JSON) +├── lib/ # Git submodules (solmate, forge-std) +├── foundry.toml # Foundry configuration +└── .env.example # Environment variables template +``` + +## Supported Chains + +| Mainnet | Testnet | +|---------|---------| +| Ethereum | Sepolia | +| Arbitrum | Arbitrum Sepolia | +| Base | Base Sepolia | +| BSC | BSC Testnet | +| Scroll | Scroll Sepolia | + +## Development Workflow + +### Setup + +```bash +# Install dependencies +forge install + +# Copy and configure environment +cp .env.example .env +# Edit .env with your values +``` + +### Build + +```bash +forge build +``` + +### Deploy + +```bash +# Deploy to a specific network +./deploy/deploy.sh + +# Example +./deploy/deploy.sh sepolia +``` + +## Important Technical Details + +### Factory Address Calculation + +The CREATE3Factory address is calculated as: +``` +address = keccak256(0xff ++ deployer ++ salt ++ keccak256(bytecode))[12:] +``` + +### User Contract Address Calculation + +When users call `factory.deploy(salt, creationCode)`: +``` +finalSalt = keccak256(msg.sender ++ userSalt) +address = f(factoryAddress, finalSalt) // Independent of creationCode +``` + +### Security Notes + +- The salt in Deploy.s.sol ("intmax") does not need to be secret +- Security relies on the deployer's private key, not the salt +- Each caller (msg.sender) has their own address namespace + +## Environment Variables + +Required in `.env`: + +```bash +PRIVATE_KEY= # Deployer private key + +# RPC URLs +RPC_URL_MAINNET= +RPC_URL_ARBITRUM= +RPC_URL_BASE= +RPC_URL_BSC= +RPC_URL_SCROLL= +RPC_URL_SEPOLIA= +RPC_URL_ARBITRUM_SEPOLIA= +RPC_URL_BASE_SEPOLIA= +RPC_URL_BSC_TESTNET= +RPC_URL_SCROLL_SEPOLIA= + +# Etherscan API Keys (for verification) +ETHERSCAN_KEY= +ARBISCAN_KEY= +BASESCAN_API_KEY= +BSCSCAN_KEY= +SCROLLSCAN_API_KEY= +``` + +## Solidity Version + +This project uses Solidity 0.8.33 with strict version pinning for bytecode determinism. diff --git a/README.md b/README.md index 362d31e..8109323 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ Factory contract for easily deploying contracts to the same address on multiple chains, using CREATE3. -This was forked from https://github.com/zeframlou/create3-factory - -The deploy script was updated to use legacy (non EIP-1559) transactions due to the fact that some chains that LIFI supports do not support EIP-1559. +This was forked from https://github.com/lifinance/create3-factory (originally from https://github.com/ZeframLou/create3-factory) ## Why? @@ -15,11 +13,19 @@ One could use a `CREATE2` factory that deterministically deploys contracts to an A `CREATE3` factory offers the best solution: the address of the deployed contract is determined by only the deployer address and the salt. This makes it far easier to deploy contracts to multiple chains at the same addresses. -LIFI Supports a large number of chains and we are only growing. CREATE3 allows us to manage our deployments better as well as make integration by developers more painless. +## Supported Chains + +| Mainnet | Testnet | +|---------|---------| +| Ethereum | Sepolia | +| Arbitrum | Arbitrum Sepolia | +| Base | Base Sepolia | +| BSC | BSC Testnet | +| Scroll | Scroll Sepolia | ## Deployments -For a list of all deployments and their respective addresses of the `CREATE3Factory` please check folder deployments/ +For a list of all deployments and their respective addresses of the `CREATE3Factory` please check folder `deployments/` ## Usage @@ -35,7 +41,7 @@ A few notes: To install with [Foundry](https://github.com/foundry-rs/foundry): ``` -forge install lifinance/create3-factory +forge install InternetMaximalism/create3-factory ``` ## Local development diff --git a/foundry.lock b/foundry.lock new file mode 100644 index 0000000..fad4f17 --- /dev/null +++ b/foundry.lock @@ -0,0 +1,8 @@ +{ + "lib/forge-std": { + "rev": "cb69e9c07fbd002819c8c6c8db3caeab76b90d6b" + }, + "lib/solmate": { + "rev": "bff24e835192470ed38bf15dbed6084c2d723ace" + } +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 62ffab8..4272b68 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,120 +1,36 @@ [profile.default] optimizer_runs = 30 -solc_version = '0.8.28' +solc_version = '0.8.33' evm_version = 'cancun' +bytecode_hash = "none" +cbor_metadata = false [rpc_endpoints] +# mainnet mainnet = "${RPC_URL_MAINNET}" -apechain = "${RPC_URL_APECHAIN}" arbitrum = "${RPC_URL_ARBITRUM}" -aurora = "${RPC_URL_AURORA}" -avalanche = "${RPC_URL_AVALANCHE}" base = "${RPC_URL_BASE}" -berachain = "${RPC_URL_BERACHAIN}" -blast = "${RPC_URL_BLAST}" -boba = "${RPC_URL_BOBA}" bsc = "${RPC_URL_BSC}" -celo = "${RPC_URL_CELO}" -corn = "${RPC_URL_CORN}" -cronos = "${RPC_URL_CRONOS}" -evmos = "${RPC_URL_EVMOS}" -fantom = "${RPC_URL_FANTOM}" -fraxtal = "${RPC_URL_FRAXTAL}" -fuse = "${RPC_URL_FUSE}" -harmony = "${RPC_URL_HARMONY}" -hyperevm = "${RPC_URL_HYPEREVM}" -gnosis = "${RPC_URL_GNOSIS}" -gravity = "${RPC_URL_GRAVITY}" -etherlink = "${RPC_URL_ETHERLINK}" -immutablezkevm = "${RPC_URL_IMMUTABLEZKEVM}" -ink = "${RPC_URL_INK}" -kaia = "${RPC_URL_KAIA}" -linea = "${RPC_URL_LINEA}" -lisk = "${RPC_URL_LISK}" -mantle = "${RPC_URL_MANTLE}" -metis = "${RPC_URL_METIS}" -mode = "${RPC_URL_MODE}" -moonbeam = "${RPC_URL_MOONBEAM}" -moonriver = "${RPC_URL_MOONRIVER}" -nova = "${RPC_URL_NOVA}" -okx = "${RPC_URL_OKX}" -opbnb = "${RPC_URL_OPBNB}" -optimism = "${RPC_URL_OPTIMISM}" -plasma = "${RPC_URL_PLASMA}" -polygon = "${RPC_URL_POLYGON}" -rootstock = "${RPC_URL_ROOTSTOCK}" scroll = "${RPC_URL_SCROLL}" -sei = "${RPC_URL_SEI}" -soneium = "${RPC_URL_SONEIUM}" -sonic = "${RPC_URL_SONIC}" -swellchain = "${RPC_URL_SWELLCHAIN}" -superposition = "${RPC_URL_SUPERPOSITION}" -taiko = "${RPC_URL_TAIKO}" -velas = "${RPC_URL_VELAS}" -xlayer = "${RPC_URL_XLAYER}" -unichain = "${RPC_URL_UNICHAIN}" -worldchain = "${RPC_URL_WORLDCHAIN}" -zksync = "${RPC_URL_ZKSYNC}" -zkevm = "${RPC_URL_ZKEVM}" -# testnets -goerli = "${RPC_URL_GOERLI}" +# testnet sepolia = "${RPC_URL_SEPOLIA}" -mumbai = "${RPC_URL_MUMBAI}" -arbitrum-goerli = "${RPC_URL_ARBITRUM_GOERLI}" -consensys-zkevm-testnet = "${RPC_URL_CONSENSYS_ZKEVM_TESTNET}" +arbitrum-sepolia = "${RPC_URL_ARBITRUM_SEPOLIA}" +base-sepolia = "${RPC_URL_BASE_SEPOLIA}" bsc-testnet = "${RPC_URL_BSC_TESTNET}" -scroll-alpha = "${RPC_URL_SCROLL_ALPHA}" -beratest = "${RPC_URL_BERATEST}" +scroll-sepolia = "${RPC_URL_SCROLL_SEPOLIA}" [etherscan] +# mainnet mainnet = { key = "${ETHERSCAN_KEY}" } -apechain = { key = "${APECHAIN_KEY}", url = "https://apechain.calderaexplorer.xyz/api", verifier = "blockscout", chain = 33139 } arbitrum = { key = "${ARBISCAN_KEY}", url = "https://api.arbiscan.io/api" } -avalanche = { key = "${SNOWTRACE_KEY}", url = "https://api.snowtrace.io/api" } base = { key = "${BASESCAN_API_KEY}", url = "https://api.basescan.org/api" } -berachain = { key = "${BERACHAIN_ETHERSCAN_API_KEY}", url = "https://api.berascan.com/api" } -blast = { key = "${BLASTSCAN_API_KEY}", url = "https://api.blastscan.org/api" } bsc = { key = "${BSCSCAN_KEY}", url = "https://api.bscscan.com/api" } -corn = { key = "${CORNSCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/21000000/etherscan" } -etherlink = { key = "${ETHERLINK_API_KEY}", url = "https://explorer.etherlink.com/api", verifier = "blockscout", chain = 42793} -fantom = { key = "${FTMSCAN_KEY}", url = "https://api.ftmscan.com/api" } -fraxtal = { key = "${FRAXSCAN_API_KEY}", url = "https://api.fraxscan.com/api" } -gnosis = { key = "${GNOSISBSCOUT_KEY}", url = "https://blockscout.com/poa/xdai/api" } -gravity = { key = "${GRAVITYSCAN_API_KEY}", url = "https://explorer.gravity.xyz/api", verifier = "blockscout", chain = 1625} -hyperevm = { key = "${HYPEREVM_API_KEY}", url = "https://hyperliquid.cloud.blockscout.com/api", verifier = "blockscout", chain = 999} -immutablezkevm = { key = "${IMMUTABLEZKEVM_API_KEY}", url = "https://explorer.immutable.com/api", verifier = "blockscout", chain = 13371} -ink = { key = "${INK_API_KEY}", url = "https://explorer.inkonchain.com/api/", verifier = "blockscout", chain = 57073} -kaia = { key = "${KAIA_API_KEY}", url = "https://kaiascope.com/api", verifier = "blockscout", chain = 8217 } -linea = { key = "${LINEASCAN_API_KEY}", url = "https://api.lineascan.build/api" } -lisk = { key = "${LISK_API_KEY}", url = "https://blockscout.lisk.com/api", chain = 1135, verifier = "blockscout" } -mantle = { key = "${MANTLESCAN_API_KEY}", url = "https://api.mantlescan.xyz/api" } -metis = { key = "${METISSCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan" } -mode = { key = "${MODESCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/34443/etherscan" } -moonbeam = { key = "${MOONBEAM_MOONSCAN_KEY}", url = "https://api-moonbeam.moonscan.io/api" } -moonriver = { key = "${MOONRIVER_MOONSCAN_KEY}", url = "https://api-moonriver.moonscan.io/api" } -nova = { key = "${NOVA_ARBISCAN_KEY}", url = "https://nova.arbiscan.io/api" } -optimism = { key = "${OPTIMISM_ETHERSCAN_KEY}", url = "https://api-optimistic.etherscan.io/api" } -plasma = { key = "${PLASMA_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/9745/etherscan" } -polygon = { key = "${POLYGONSCAN_KEY}", url = "https://api.polygonscan.com/api" } -rootstock = { key = "${RSKSCAN_API_KEY}", url = "https://api.rskscan.com/api" } scroll = { key = "${SCROLLSCAN_API_KEY}", url = "https://api.scrollscan.com/api" } -sei = { key = "${SEISCAN_API_KEY}", url = "https://api.seitrace.com/api" } -soneium = { key = "${SONEIUM_API_KEY}", url = "https://soneium.blockscout.com/api?", verifier = "blockscout", chain = 1868 } -sonic = { key = "${SONICSCAN_API_KEY}", url = "https://api.sonicscan.com/api" } -swellchain = { key = "${SWELLCHAIN_API_KEY}", url = "https://api.swellchainscan.io/api", chain = 1923 } -superposition = { key = "${SUPERPOSITION_API_KEY}", url = "https://explorer.superposition.so/api", chain = 55244, verifier = "blockscout" } -taiko = { key = "${TAIKO_API_KEY}", url = "https://api.taikoscan.io/api" } -unichain = { key = "${UNICHAIN_API_KEY}", url = "https://unichain.blockscout.com/?", chain = 130 , verifier = "blockscout" } -worldchain = { key = "${WORLDCHAIN_API_KEY}", url = "https://api.worldscan.org/api" } -xlayer = { key = "${XLAYER_API_KEY}", url = "https://www.oklink.com/api/v5/explorer/xlayer/api", chain = 196 } -#testnets -goerli = { key = "${ETHERSCAN_KEY}" } +# testnet sepolia = { key = "${ETHERSCAN_KEY}" } -mumbai = { key = "${POLYGONSCAN_KEY}", url = "https://api-testnet.polygonscan.com/api" } -arbitrum-goerli = { key = "${ARBISCAN_KEY}", url = "https://api-goerli.arbiscan.io/api" } -beratest = { key = "${BERATEST_API_KEY}", url = "https://api.routescan.io/v2/network/testnet/evm/80084/etherscan/api", chain = "80084" } - -# See more config options https://github.com/foundry-rs/foundry/tree/master/config -# +arbitrum-sepolia = { key = "${ARBISCAN_KEY}", url = "https://api-sepolia.arbiscan.io/api" } +base-sepolia = { key = "${BASESCAN_API_KEY}", url = "https://api-sepolia.basescan.org/api" } +bsc-testnet = { key = "${BSCSCAN_KEY}", url = "https://api-testnet.bscscan.com/api" } +scroll-sepolia = { key = "${SCROLLSCAN_API_KEY}", url = "https://api-sepolia.scrollscan.com/api" } diff --git a/package.json b/package.json new file mode 100644 index 0000000..57fd3e5 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "create3-factory", + "version": "1.0.0", + "description": "Factory contract for deterministic contract deployment across multiple EVM chains using CREATE3", + "scripts": { + "lint": "solhint 'src/**/*.sol' 'script/**/*.sol' 'test/**/*.sol'", + "lint:fix": "solhint 'src/**/*.sol' 'script/**/*.sol' 'test/**/*.sol' --fix" + }, + "keywords": [ + "solidity", + "ethereum", + "create3", + "create2", + "deterministic-deployment", + "multichain", + "foundry" + ], + "author": "", + "license": "AGPL-3.0", + "devDependencies": { + "solhint": "6.0.1" + } +} diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 4e00aa8..6810a18 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -8,10 +8,11 @@ import {CREATE3Factory} from "../src/CREATE3Factory.sol"; contract DeployScript is Script { function run() public returns (CREATE3Factory factory) { uint256 deployerPrivateKey = uint256(vm.envBytes32("PRIVATE_KEY")); + bytes32 salt = keccak256("intmax"); vm.startBroadcast(deployerPrivateKey); - factory = new CREATE3Factory(); + factory = new CREATE3Factory{salt: salt}(); vm.stopBroadcast(); } diff --git a/slither.config.json b/slither.config.json new file mode 100644 index 0000000..877a0e7 --- /dev/null +++ b/slither.config.json @@ -0,0 +1,4 @@ +{ + "filter_paths": "verifiers,dependencies,node_modules", + "detectors_to_exclude": "msg-value-loop,assembly,low-level-calls,naming-convention,unindexed-event-address" +} diff --git a/src/CREATE3Factory.flattened b/src/CREATE3Factory.flattened index d991094..0c3e5b0 100644 --- a/src/CREATE3Factory.flattened +++ b/src/CREATE3Factory.flattened @@ -1,5 +1,5 @@ // SPDX-License-Identifier: AGPL-3.0 -pragma solidity >=0.6.0 >=0.8.0 ^0.8.13; +pragma solidity 0.8.33; // lib/solmate/src/utils/Bytes32AddressLib.sol diff --git a/src/CREATE3Factory.sol b/src/CREATE3Factory.sol index 17133d2..27d444e 100644 --- a/src/CREATE3Factory.sol +++ b/src/CREATE3Factory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: AGPL-3.0 -pragma solidity ^0.8.13; +pragma solidity 0.8.33; import {CREATE3} from "solmate/utils/CREATE3.sol"; @@ -11,24 +11,14 @@ import {ICREATE3Factory} from "./ICREATE3Factory.sol"; /// its own namespace for deployed addresses. contract CREATE3Factory is ICREATE3Factory { /// @inheritdoc ICREATE3Factory - function deploy(bytes32 salt, bytes memory creationCode) - external - payable - override - returns (address deployed) - { + function deploy(bytes32 salt, bytes memory creationCode) external payable override returns (address deployed) { // hash salt with the deployer address to give each deployer its own namespace salt = keccak256(abi.encodePacked(msg.sender, salt)); return CREATE3.deploy(salt, creationCode, msg.value); } /// @inheritdoc ICREATE3Factory - function getDeployed(address deployer, bytes32 salt) - external - view - override - returns (address deployed) - { + function getDeployed(address deployer, bytes32 salt) external view override returns (address deployed) { // hash salt with the deployer address to give each deployer its own namespace salt = keccak256(abi.encodePacked(deployer, salt)); return CREATE3.getDeployed(salt); diff --git a/src/ICREATE3Factory.sol b/src/ICREATE3Factory.sol index 59abc8d..38ae2fc 100644 --- a/src/ICREATE3Factory.sol +++ b/src/ICREATE3Factory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: AGPL-3.0 -pragma solidity >=0.6.0; +pragma solidity ^0.8.24; /// @title Factory for deploying contracts to deterministic addresses via CREATE3 /// @author zefram.eth @@ -11,18 +11,12 @@ interface ICREATE3Factory { /// @param salt The deployer-specific salt for determining the deployed contract's address /// @param creationCode The creation code of the contract to deploy /// @return deployed The address of the deployed contract - function deploy(bytes32 salt, bytes memory creationCode) - external - payable - returns (address deployed); + function deploy(bytes32 salt, bytes memory creationCode) external payable returns (address deployed); /// @notice Predicts the address of a deployed contract /// @dev The provided salt is hashed together with the deployer address to generate the final salt /// @param deployer The deployer account that will call deploy() /// @param salt The deployer-specific salt for determining the deployed contract's address /// @return deployed The address of the contract that will be deployed - function getDeployed(address deployer, bytes32 salt) - external - view - returns (address deployed); + function getDeployed(address deployer, bytes32 salt) external view returns (address deployed); } diff --git a/test/CREATE3Factory.t.sol b/test/CREATE3Factory.t.sol new file mode 100644 index 0000000..b98aa02 --- /dev/null +++ b/test/CREATE3Factory.t.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.33; + +import {Test} from "forge-std/Test.sol"; +import {CREATE3Factory} from "../src/CREATE3Factory.sol"; + +/// @dev Simple contract for testing deployment +contract MockContract { + uint256 public value; + address public deployer; + + constructor(uint256 _value) payable { + value = _value; + deployer = msg.sender; // Note: This will be the CREATE3 proxy, not the actual deployer + } + + function setValue(uint256 _value) external { + value = _value; + } +} + +/// @dev Contract that requires ETH in constructor +contract PayableContract { + uint256 public balance; + + constructor() payable { + balance = msg.value; + } +} + +contract CREATE3FactoryTest is Test { + CREATE3Factory public factory; + + address public alice = address(0x1); + address public bob = address(0x2); + + bytes32 public constant SALT = keccak256("test-salt"); + bytes32 public constant SALT_2 = keccak256("test-salt-2"); + + function setUp() public { + factory = new CREATE3Factory(); + } + + /*////////////////////////////////////////////////////////////// + DEPLOY TESTS + //////////////////////////////////////////////////////////////*/ + + function test_deploy_basic() public { + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(42)); + + address deployed = factory.deploy(SALT, creationCode); + + assertTrue(deployed != address(0), "Deployed address should not be zero"); + assertTrue(deployed.code.length > 0, "Deployed contract should have code"); + + MockContract mock = MockContract(deployed); + assertEq(mock.value(), 42, "Constructor argument should be set correctly"); + } + + function test_deploy_predictedAddressMatches() public { + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(100)); + + address predicted = factory.getDeployed(address(this), SALT); + address deployed = factory.deploy(SALT, creationCode); + + assertEq(deployed, predicted, "Deployed address should match predicted address"); + } + + function test_deploy_differentSaltsProduceDifferentAddresses() public { + address predicted1 = factory.getDeployed(address(this), SALT); + address predicted2 = factory.getDeployed(address(this), SALT_2); + + assertTrue(predicted1 != predicted2, "Different salts should produce different addresses"); + } + + function test_deploy_differentDeployersProduceDifferentAddresses() public { + address predictedAlice = factory.getDeployed(alice, SALT); + address predictedBob = factory.getDeployed(bob, SALT); + + assertTrue(predictedAlice != predictedBob, "Different deployers should produce different addresses"); + } + + function test_deploy_sameSaltSameDeployerProducesSameAddress() public { + address predicted1 = factory.getDeployed(address(this), SALT); + address predicted2 = factory.getDeployed(address(this), SALT); + + assertEq(predicted1, predicted2, "Same salt and deployer should produce same address"); + } + + function test_deploy_withValue() public { + uint256 sendValue = 1 ether; + vm.deal(address(this), sendValue); + + bytes memory creationCode = type(PayableContract).creationCode; + + address deployed = factory.deploy{value: sendValue}(SALT, creationCode); + + PayableContract payable_ = PayableContract(deployed); + assertEq(payable_.balance(), sendValue, "Deployed contract should receive ETH"); + assertEq(deployed.balance, sendValue, "Contract balance should match sent value"); + } + + function test_deploy_revertOnDuplicateDeploy() public { + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(42)); + + factory.deploy(SALT, creationCode); + + vm.expectRevert(); + factory.deploy(SALT, creationCode); + } + + function test_deploy_fromDifferentAccounts() public { + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(42)); + + vm.prank(alice); + address deployedByAlice = factory.deploy(SALT, creationCode); + + vm.prank(bob); + address deployedByBob = factory.deploy(SALT, creationCode); + + assertTrue(deployedByAlice != deployedByBob, "Same salt from different accounts should produce different addresses"); + + assertEq(deployedByAlice, factory.getDeployed(alice, SALT), "Alice's deployed address should match prediction"); + assertEq(deployedByBob, factory.getDeployed(bob, SALT), "Bob's deployed address should match prediction"); + } + + /*////////////////////////////////////////////////////////////// + GETDEPLOYED TESTS + //////////////////////////////////////////////////////////////*/ + + function test_getDeployed_consistentBeforeAndAfterDeploy() public { + address predictedBefore = factory.getDeployed(address(this), SALT); + + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(42)); + factory.deploy(SALT, creationCode); + + address predictedAfter = factory.getDeployed(address(this), SALT); + + assertEq(predictedBefore, predictedAfter, "Predicted address should be consistent before and after deploy"); + } + + function test_getDeployed_independentOfCreationCode() public { + // The address should be the same regardless of what contract will be deployed + address predicted = factory.getDeployed(address(this), SALT); + + // Deploy a different contract + bytes memory creationCode = type(PayableContract).creationCode; + address deployed = factory.deploy(SALT, creationCode); + + assertEq(deployed, predicted, "Address should be independent of creation code"); + } + + /*////////////////////////////////////////////////////////////// + FUZZ TESTS + //////////////////////////////////////////////////////////////*/ + + function testFuzz_deploy_predictedAddressMatches(bytes32 salt, uint256 value) public { + bytes memory creationCode = abi.encodePacked(type(MockContract).creationCode, abi.encode(value)); + + address predicted = factory.getDeployed(address(this), salt); + address deployed = factory.deploy(salt, creationCode); + + assertEq(deployed, predicted, "Deployed address should match predicted address"); + } + + function testFuzz_getDeployed_differentSaltsProduceDifferentAddresses(bytes32 salt1, bytes32 salt2) public { + vm.assume(salt1 != salt2); + + address predicted1 = factory.getDeployed(address(this), salt1); + address predicted2 = factory.getDeployed(address(this), salt2); + + assertTrue(predicted1 != predicted2, "Different salts should produce different addresses"); + } + + function testFuzz_getDeployed_differentDeployersProduceDifferentAddresses(address deployer1, address deployer2) public { + vm.assume(deployer1 != deployer2); + + address predicted1 = factory.getDeployed(deployer1, SALT); + address predicted2 = factory.getDeployed(deployer2, SALT); + + assertTrue(predicted1 != predicted2, "Different deployers should produce different addresses"); + } +} From f1b223e4db628067418b3223b8c60abebd4b405b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAkira-Taniguchi=E2=80=9D?= <“dededededaiou2003@yahoo.co.jp”> Date: Mon, 2 Feb 2026 14:40:06 +0900 Subject: [PATCH 2/4] test --- .solhint.json | 1 - foundry.toml | 1 + script/Deploy.s.sol | 4 ++-- slither.config.json | 7 +++++-- test/CREATE3Factory.t.sol | 8 ++++++-- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.solhint.json b/.solhint.json index bd8ca44..2d4c118 100644 --- a/.solhint.json +++ b/.solhint.json @@ -2,7 +2,6 @@ "extends": "solhint:recommended", "rules": { "import-path-check": "off", - "use-natspec": "off", "func-visibility": ["warn", {"ignoreConstructors": true}], "gas-strict-inequalities": "off", "gas-indexed-events": "off", diff --git a/foundry.toml b/foundry.toml index 4272b68..d42d6b2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,6 +4,7 @@ solc_version = '0.8.33' evm_version = 'cancun' bytecode_hash = "none" cbor_metadata = false +ignored_warnings_from = ["lib/"] [rpc_endpoints] # mainnet diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 6810a18..00be405 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; +pragma solidity 0.8.33; -import "forge-std/Script.sol"; +import {Script} from "forge-std/Script.sol"; import {CREATE3Factory} from "../src/CREATE3Factory.sol"; diff --git a/slither.config.json b/slither.config.json index 877a0e7..8a18aaa 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,4 +1,7 @@ { - "filter_paths": "verifiers,dependencies,node_modules", - "detectors_to_exclude": "msg-value-loop,assembly,low-level-calls,naming-convention,unindexed-event-address" + "filter_paths": "lib/", + "exclude_informational": false, + "exclude_low": false, + "exclude_medium": false, + "exclude_high": false } diff --git a/test/CREATE3Factory.t.sol b/test/CREATE3Factory.t.sol index b98aa02..8fc3e6c 100644 --- a/test/CREATE3Factory.t.sol +++ b/test/CREATE3Factory.t.sol @@ -118,7 +118,9 @@ contract CREATE3FactoryTest is Test { vm.prank(bob); address deployedByBob = factory.deploy(SALT, creationCode); - assertTrue(deployedByAlice != deployedByBob, "Same salt from different accounts should produce different addresses"); + assertTrue( + deployedByAlice != deployedByBob, "Same salt from different accounts should produce different addresses" + ); assertEq(deployedByAlice, factory.getDeployed(alice, SALT), "Alice's deployed address should match prediction"); assertEq(deployedByBob, factory.getDeployed(bob, SALT), "Bob's deployed address should match prediction"); @@ -172,7 +174,9 @@ contract CREATE3FactoryTest is Test { assertTrue(predicted1 != predicted2, "Different salts should produce different addresses"); } - function testFuzz_getDeployed_differentDeployersProduceDifferentAddresses(address deployer1, address deployer2) public { + function testFuzz_getDeployed_differentDeployersProduceDifferentAddresses(address deployer1, address deployer2) + public + { vm.assume(deployer1 != deployer2); address predicted1 = factory.getDeployed(deployer1, SALT); From e423fba02e13ab54738e85e19c92cd56b16fe358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAkira-Taniguchi=E2=80=9D?= <“dededededaiou2003@yahoo.co.jp”> Date: Mon, 2 Feb 2026 14:47:33 +0900 Subject: [PATCH 3/4] ci --- foundry.toml | 9 ++ src/CREATE3Factory.flattened | 156 ----------------------------------- 2 files changed, 9 insertions(+), 156 deletions(-) delete mode 100644 src/CREATE3Factory.flattened diff --git a/foundry.toml b/foundry.toml index d42d6b2..733b536 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,6 +6,15 @@ bytecode_hash = "none" cbor_metadata = false ignored_warnings_from = ["lib/"] +[profile.ci] +optimizer_runs = 30 +solc_version = '0.8.33' +evm_version = 'cancun' +bytecode_hash = "none" +cbor_metadata = false +ignored_warnings_from = ["lib/"] +fuzz = { runs = 10000 } + [rpc_endpoints] # mainnet mainnet = "${RPC_URL_MAINNET}" diff --git a/src/CREATE3Factory.flattened b/src/CREATE3Factory.flattened deleted file mode 100644 index 0c3e5b0..0000000 --- a/src/CREATE3Factory.flattened +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.8.33; - -// lib/solmate/src/utils/Bytes32AddressLib.sol - -/// @notice Library for converting between addresses and bytes32 values. -/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol) -library Bytes32AddressLib { - function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { - return address(uint160(uint256(bytesValue))); - } - - function fillLast12Bytes(address addressValue) internal pure returns (bytes32) { - return bytes32(bytes20(addressValue)); - } -} - -// src/ICREATE3Factory.sol - -/// @title Factory for deploying contracts to deterministic addresses via CREATE3 -/// @author zefram.eth -/// @notice Enables deploying contracts using CREATE3. Each deployer (msg.sender) has -/// its own namespace for deployed addresses. -interface ICREATE3Factory { - /// @notice Deploys a contract using CREATE3 - /// @dev The provided salt is hashed together with msg.sender to generate the final salt - /// @param salt The deployer-specific salt for determining the deployed contract's address - /// @param creationCode The creation code of the contract to deploy - /// @return deployed The address of the deployed contract - function deploy(bytes32 salt, bytes memory creationCode) - external - payable - returns (address deployed); - - /// @notice Predicts the address of a deployed contract - /// @dev The provided salt is hashed together with the deployer address to generate the final salt - /// @param deployer The deployer account that will call deploy() - /// @param salt The deployer-specific salt for determining the deployed contract's address - /// @return deployed The address of the contract that will be deployed - function getDeployed(address deployer, bytes32 salt) - external - view - returns (address deployed); -} - -// lib/solmate/src/utils/CREATE3.sol - -/// @notice Deploy to deterministic addresses without an initcode factor. -/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) -/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) -library CREATE3 { - using Bytes32AddressLib for bytes32; - - //--------------------------------------------------------------------------------// - // Opcode | Opcode + Arguments | Description | Stack View // - //--------------------------------------------------------------------------------// - // 0x36 | 0x36 | CALLDATASIZE | size // - // 0x3d | 0x3d | RETURNDATASIZE | 0 size // - // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // - // 0x37 | 0x37 | CALLDATACOPY | // - // 0x36 | 0x36 | CALLDATASIZE | size // - // 0x3d | 0x3d | RETURNDATASIZE | 0 size // - // 0x34 | 0x34 | CALLVALUE | value 0 size // - // 0xf0 | 0xf0 | CREATE | newContract // - //--------------------------------------------------------------------------------// - // Opcode | Opcode + Arguments | Description | Stack View // - //--------------------------------------------------------------------------------// - // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode // - // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode // - // 0x52 | 0x52 | MSTORE | // - // 0x60 | 0x6008 | PUSH1 08 | 8 // - // 0x60 | 0x6018 | PUSH1 18 | 24 8 // - // 0xf3 | 0xf3 | RETURN | // - //--------------------------------------------------------------------------------// - bytes internal constant PROXY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3"; - - bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE); - - function deploy( - bytes32 salt, - bytes memory creationCode, - uint256 value - ) internal returns (address deployed) { - bytes memory proxyChildBytecode = PROXY_BYTECODE; - - address proxy; - assembly { - // Deploy a new contract with our pre-made bytecode via CREATE2. - // We start 32 bytes into the code to avoid copying the byte length. - proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt) - } - require(proxy != address(0), "DEPLOYMENT_FAILED"); - - deployed = getDeployed(salt); - (bool success, ) = proxy.call{value: value}(creationCode); - require(success && deployed.code.length != 0, "INITIALIZATION_FAILED"); - } - - function getDeployed(bytes32 salt) internal view returns (address) { - address proxy = keccak256( - abi.encodePacked( - // Prefix: - bytes1(0xFF), - // Creator: - address(this), - // Salt: - salt, - // Bytecode hash: - PROXY_BYTECODE_HASH - ) - ).fromLast20Bytes(); - - return - keccak256( - abi.encodePacked( - // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01) - // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) - hex"d6_94", - proxy, - hex"01" // Nonce of the proxy contract (1) - ) - ).fromLast20Bytes(); - } -} - -// src/CREATE3Factory.sol - -/// @title Factory for deploying contracts to deterministic addresses via CREATE3 -/// @author zefram.eth -/// @notice Enables deploying contracts using CREATE3. Each deployer (msg.sender) has -/// its own namespace for deployed addresses. -contract CREATE3Factory is ICREATE3Factory { - /// - function deploy(bytes32 salt, bytes memory creationCode) - external - payable - override - returns (address deployed) - { - // hash salt with the deployer address to give each deployer its own namespace - salt = keccak256(abi.encodePacked(msg.sender, salt)); - return CREATE3.deploy(salt, creationCode, msg.value); - } - - /// - function getDeployed(address deployer, bytes32 salt) - external - view - override - returns (address deployed) - { - // hash salt with the deployer address to give each deployer its own namespace - salt = keccak256(abi.encodePacked(deployer, salt)); - return CREATE3.getDeployed(salt); - } -} From cb1e66902f911bd35a6667d8760e71ca6db7bcd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAkira-Taniguchi=E2=80=9D?= <“dededededaiou2003@yahoo.co.jp”> Date: Mon, 2 Feb 2026 14:52:49 +0900 Subject: [PATCH 4/4] Add package-lock.json for CI --- package-lock.json | 1250 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1250 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5a71281 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1250 @@ +{ + "name": "create3-factory", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "create3-factory", + "version": "1.0.0", + "license": "AGPL-3.0", + "devDependencies": { + "solhint": "6.0.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/npm-conf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.2.tgz", + "integrity": "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.2.tgz", + "integrity": "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", + "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/ast-parents": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", + "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/better-ajv-errors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-2.0.3.tgz", + "integrity": "sha512-t1vxUP+vYKsaYi/BbKo2K98nEAZmfi4sjwvmRT8aOPDzPJeAtLurfoIDazVkLILxO4K+Sw4YrLYnBQ46l6pePg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@humanwhocodes/momoa": "^2.0.4", + "chalk": "^4.1.2", + "jsonpointer": "^5.0.1", + "leven": "^3.1.0 < 4" + }, + "engines": { + "node": ">= 18.20.6" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/normalize-url": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dev": true, + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^3.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/solhint": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-6.0.1.tgz", + "integrity": "sha512-Lew5nhmkXqHPybzBzkMzvvWkpOJSSLTkfTZwRriWvfR2naS4YW2PsjVGaoX9tZFmHh7SuS+e2GEGo5FPYYmJ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@solidity-parser/parser": "^0.20.2", + "ajv": "^6.12.6", + "ajv-errors": "^1.0.1", + "antlr4": "^4.13.1-patch-1", + "ast-parents": "^0.0.1", + "better-ajv-errors": "^2.0.2", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "cosmiconfig": "^8.0.0", + "fast-diff": "^1.2.0", + "glob": "^8.0.3", + "ignore": "^5.2.4", + "js-yaml": "^4.1.0", + "latest-version": "^7.0.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "semver": "^7.5.2", + "table": "^6.8.1", + "text-table": "^0.2.0" + }, + "bin": { + "solhint": "solhint.js" + }, + "optionalDependencies": { + "prettier": "^2.8.3" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +}