diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 762a296..9626396 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,17 +29,7 @@ jobs: run: | forge --version - - name: Run Forge fmt - run: | - forge fmt --check - id: fmt - - - name: Run Forge build - run: | - forge build --sizes - id: build - - name: Run Forge tests run: | - forge test -vvv + forge test --build-info --force --via-ir -vvv id: test diff --git a/.gitignore b/.gitignore index efc650f..389c819 100644 --- a/.gitignore +++ b/.gitignore @@ -6,12 +6,32 @@ cache/ out/ # Ignores development broadcast logs -!/broadcast -/broadcast/*/31337/ -/broadcast/**/dry-run/ +/broadcast # Docs docs/ # Dotenv file .env + +node_modules +.env + +# Hardhat files +/cache-hardhat +/out-hardhat + +# TypeChain files +/typechain +/typechain-types + +# solidity-coverage files +/coverage +/coverage.json + +# Hardhat Ignition default folder for deployments against a local node +ignition/deployments/chain-31337 + +# Localhost deployment files +deployments/31337_localhost +deployments/1337_localhost diff --git a/.husky/commit-msg b/.husky/commit-msg index 069ac29..5d86529 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,3 +1,3 @@ echo "๐Ÿ™ Performing commit message checks..." -npx --no -- commitlint --edit ${1} +pnpm commitlint --edit ${1} echo "Your commit message is a work of art. Chef kiss ๐Ÿง‘โ€๐Ÿณ๐Ÿ˜™๐ŸคŒ. Nice job ๐Ÿ‘" \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 0138d54..5c5b38e 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,18 +1,9 @@ +# Linting echo "๐Ÿ•บ Performing linting checks..." -npx lint-staged +pnpm exec lint-staged echo "Your code is beautiful, nice job ๐Ÿ‘" -echo "๐Ÿงช Running tests..." -if git diff --cached --name-only | grep -q "\.sol$"; then - if ls test/**/*.sol 1> /dev/null 2>&1; then - if ! forge test; then - echo "โŒ Tests failed! Please fix before committing." - exit 1 - fi - echo "All tests passed ๐Ÿš€" - else - echo "No Solidity test files found, skipping tests..." - fi -else - echo "No Solidity files in staged changes, skipping..." -fi +# Compilation test +echo "Hold'on, we're making sure yer code compiles ๐Ÿ‘จโ€๐Ÿณ" +forge build --skip 'test' --skip 'script' --build-info --force +echo "It worked this time, keep on doing gud stuffs ๐ŸŽ‰" diff --git a/.openzeppelin/unknown-1287.json b/.openzeppelin/unknown-1287.json new file mode 100644 index 0000000..0a32e88 --- /dev/null +++ b/.openzeppelin/unknown-1287.json @@ -0,0 +1,841 @@ +{ + "manifestVersion": "3.2", + "proxies": [ + { + "address": "0x2CD45db1754b74dddbE42F742BB10B70D0AC7819", + "txHash": "0x7754b58a2febd1caabdab25bebd063d4765a0ab69bf6bf6172a51faee5c205da", + "kind": "transparent" + }, + { + "address": "0x42aADFe321D6d383b1355C6B9EA47D13D2B98dF7", + "txHash": "0x8dbdccac3061a6d95d2fa2541b1267e65d0751b1953321a66c17b69e4ebc0ef4", + "kind": "transparent" + }, + { + "address": "0x8200e4d81E0de50cabb2e4d17848AB8170486106", + "txHash": "0x4054cd2c708fb0e8b1e6b4245fa18bcb43dee8a8bca5c78b54b7f010f6cc54f3", + "kind": "transparent" + }, + { + "address": "0x56ad3C6b27C80c1AD6D5a09FE57b95278655C546", + "txHash": "0xb1efab7a95acf418e19f93cb89e84e97967090f1662aed392fdd2e33fbdfe971", + "kind": "transparent" + }, + { + "address": "0x6D773D69793c5C2Dae5644bdd9692317602F5b5c", + "txHash": "0x719172f309593d715b8f070d59ae0ac3cfedccd3ebc703d7ccc1a06f39a7113c", + "kind": "transparent" + }, + { + "address": "0x3ccAfAF321718c033973405688e2A285d542A586", + "txHash": "0x403695a3d05c2960d9f0021ae4c0017323ca4e6a30871191c3c6edaad8b640fe", + "kind": "transparent" + }, + { + "address": "0xC895303deBfAcE3daE08BC7Af5ce172A0968f341", + "txHash": "0xa2e0b341b87d0839cb63a1620f4afa2581a54681bd8545ac27e142ee6bb10f9e", + "kind": "transparent" + }, + { + "address": "0xD1b11fE68a7e363E5564aB86AB496Ec9C4eB125d", + "txHash": "0x0cf7f78d43bf3a03e4f743ebb7d4d4431923e20e63e6d3d2f2bf5a2f487be8bf", + "kind": "transparent" + } + ], + "impls": { + "0bdcb7bfd14d81d67833a73a77cbffad5dba3fbbf3dec8596554814246c48ea5": { + "address": "0x5250Ca602b5B84CbeafE3070Ddb042f051232C83", + "txHash": "0xe545dfd48276cc19f7d8eede4c8cd0af3e215f3e04edcbfb4e0900dee0805f8c", + "layout": { + "solcVersion": "0.8.26", + "storage": [ + { + "label": "projects", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint64,t_struct(Project)44088_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:255" + }, + { + "label": "pools", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_struct(Pool)44208_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:256" + }, + { + "label": "vAssetToNativeAsset", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_address)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:257" + }, + { + "label": "nextProjectId", + "offset": 0, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:258" + }, + { + "label": "nextPoolId", + "offset": 8, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:259" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)17873_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)17813_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_enum(PoolType)44081": { + "label": "enum PoolTypeLib.PoolType", + "members": [ + "LAUNCHPOOL", + "LAUNCHPAD", + "VESTING", + "FARMING" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Pool)44208_storage)": { + "label": "mapping(uint64 => struct LaunchpoolLibrary.Pool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Project)44088_storage)": { + "label": "mapping(uint64 => struct ProjectLibrary.Project)", + "numberOfBytes": "32" + }, + "t_struct(Pool)44208_storage": { + "label": "struct LaunchpoolLibrary.Pool", + "members": [ + { + "label": "poolId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "poolType", + "type": "t_enum(PoolType)44081", + "offset": 8, + "slot": "0" + }, + { + "label": "poolAddress", + "type": "t_address", + "offset": 9, + "slot": "0" + }, + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "isListed", + "type": "t_bool", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Project)44088_storage": { + "label": "struct ProjectLibrary.Project", + "members": [ + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "projectOwner", + "type": "t_address", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:24", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "8cbe6f83a339245783d1af66cf7fceb86417e11a4757715e3b64357744f072ba": { + "address": "0x5414f5757E61669ee72744eD676B4aA3Bb7da314", + "txHash": "0xb8788737abed97f29aede847c5f86db8a80757c34269e43c3daa34aac215fe81", + "layout": { + "solcVersion": "0.8.26", + "storage": [ + { + "label": "projects", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint64,t_struct(Project)44094_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:233" + }, + { + "label": "pools", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_struct(Pool)44212_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:234" + }, + { + "label": "vAssetToNativeAsset", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_address)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:235" + }, + { + "label": "nextProjectId", + "offset": 0, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:236" + }, + { + "label": "nextPoolId", + "offset": 8, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:237" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)17873_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)17813_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_enum(PoolType)44087": { + "label": "enum PoolTypeLib.PoolType", + "members": [ + "LAUNCHPOOL", + "LAUNCHPAD", + "VESTING", + "FARMING" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Pool)44212_storage)": { + "label": "mapping(uint64 => struct LaunchpoolLibrary.Pool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Project)44094_storage)": { + "label": "mapping(uint64 => struct ProjectLibrary.Project)", + "numberOfBytes": "32" + }, + "t_struct(Pool)44212_storage": { + "label": "struct LaunchpoolLibrary.Pool", + "members": [ + { + "label": "poolId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "poolType", + "type": "t_enum(PoolType)44087", + "offset": 8, + "slot": "0" + }, + { + "label": "poolAddress", + "type": "t_address", + "offset": 9, + "slot": "0" + }, + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Project)44094_storage": { + "label": "struct ProjectLibrary.Project", + "members": [ + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "projectOwner", + "type": "t_address", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:24", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "b69fc68417dcab7dc23eb17477749f1cb5da1798ce9872f2c4440fc56d263179": { + "address": "0xF5C47f3834A9f10734a21544D1C31f432be52476", + "txHash": "0xcb5b603191571639efe748725d4c967e0bed943776f5335b14948f566554b6d3", + "layout": { + "solcVersion": "0.8.26", + "storage": [ + { + "label": "projects", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint64,t_struct(Project)54585_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:235" + }, + { + "label": "pools", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_struct(Pool)54703_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:236" + }, + { + "label": "vAssetToNativeAsset", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_address)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:237" + }, + { + "label": "nextProjectId", + "offset": 0, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:238" + }, + { + "label": "nextPoolId", + "offset": 8, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:239" + }, + { + "label": "xcmOracleAddress", + "offset": 0, + "slot": "4", + "type": "t_address", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:240" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)17911_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)17851_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_enum(PoolType)54578": { + "label": "enum PoolTypeLib.PoolType", + "members": [ + "LAUNCHPOOL", + "LAUNCHPAD", + "VESTING", + "FARMING" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Pool)54703_storage)": { + "label": "mapping(uint64 => struct LaunchpoolLibrary.Pool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Project)54585_storage)": { + "label": "mapping(uint64 => struct ProjectLibrary.Project)", + "numberOfBytes": "32" + }, + "t_struct(Pool)54703_storage": { + "label": "struct LaunchpoolLibrary.Pool", + "members": [ + { + "label": "poolId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "poolType", + "type": "t_enum(PoolType)54578", + "offset": 8, + "slot": "0" + }, + { + "label": "poolAddress", + "type": "t_address", + "offset": 9, + "slot": "0" + }, + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Project)54585_storage": { + "label": "struct ProjectLibrary.Project", + "members": [ + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "projectOwner", + "type": "t_address", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:24", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "3628b7b7d86db8d76a4aad2eacf8ecacdde105aa8df19adda5d7cd0e8bd23572": { + "address": "0x2116404EaFDb0416BB99c09EC855f46F9b5173fE", + "txHash": "0x7cf673aac7d0736313c78ba91786cd03ec96f63403eefd227c32ded3b14ccef1", + "layout": { + "solcVersion": "0.8.26", + "storage": [ + { + "label": "projects", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint64,t_struct(Project)54590_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:235" + }, + { + "label": "pools", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_struct(Pool)54708_storage)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:236" + }, + { + "label": "vAssetToNativeAsset", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_address)", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:237" + }, + { + "label": "nextProjectId", + "offset": 0, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:238" + }, + { + "label": "nextPoolId", + "offset": 8, + "slot": "3", + "type": "t_uint64", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:239" + }, + { + "label": "xcmOracleAddress", + "offset": 0, + "slot": "4", + "type": "t_address", + "contract": "ProjectHubUpgradeable", + "src": "src/upgradeable/v1/ProjectHubUpgradeable.sol:240" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)17911_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)17851_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_enum(PoolType)54583": { + "label": "enum PoolTypeLib.PoolType", + "members": [ + "LAUNCHPOOL", + "LAUNCHPAD", + "VESTING", + "FARMING" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Pool)54708_storage)": { + "label": "mapping(uint64 => struct LaunchpoolLibrary.Pool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(Project)54590_storage)": { + "label": "mapping(uint64 => struct ProjectLibrary.Project)", + "numberOfBytes": "32" + }, + "t_struct(Pool)54708_storage": { + "label": "struct LaunchpoolLibrary.Pool", + "members": [ + { + "label": "poolId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "poolType", + "type": "t_enum(PoolType)54583", + "offset": 8, + "slot": "0" + }, + { + "label": "poolAddress", + "type": "t_address", + "offset": 9, + "slot": "0" + }, + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Project)54590_storage": { + "label": "struct ProjectLibrary.Project", + "members": [ + { + "label": "projectId", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "projectOwner", + "type": "t_address", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:24", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + } + } +} diff --git a/.prettierignore b/.prettierignore index 946edd0..b77c4d6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,3 +10,6 @@ package.json .github .husky .vscode +remappings.txt +deployments/ +.openzeppelin \ No newline at end of file diff --git a/.solhintignore b/.solhintignore new file mode 100644 index 0000000..d4ff4d9 --- /dev/null +++ b/.solhintignore @@ -0,0 +1,3 @@ +node_modules/** +test/** +scripts/** \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 72e1f5f..6b15cfb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,4 +13,14 @@ "[jsonc]": { "editor.tabSize": 4, }, + "peacock.color": "#42b883", + "workbench.colorCustomizations": { + "statusBar.background": "#42b883", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#359268", + "statusBarItem.remoteBackground": "#42b883", + "statusBarItem.remoteForeground": "#15202b", + "statusBar.debuggingBackground": "#b84277", + "statusBar.debuggingForeground": "#e7e7e7" + }, } \ No newline at end of file diff --git a/chain-manifest.json b/chain-manifest.json new file mode 100644 index 0000000..2ad35b5 --- /dev/null +++ b/chain-manifest.json @@ -0,0 +1,42 @@ +{ + "1": { + "name": "ethereum", + "id": 1, + "type": "mainnet" + }, + "592": { + "name": "astar", + "id": 592, + "type": "mainnet" + }, + "3772": { + "name": "astar_zkevm", + "id": 3772, + "type": "mainnet" + }, + "1284": { + "name": "moonbeam", + "id": 1284, + "type": "mainnet" + }, + "1285": { + "name": "moonriver", + "id": 1285, + "type": "mainnet" + }, + "1287": { + "name": "moonbase_alpha", + "id": 1287, + "type": "testnet" + }, + "31337": { + "name": "localhost", + "id": 31337, + "type": "local" + }, + "11155111": { + "name": "sepolia", + "id": 11155111, + "type": "testnet" + } +} diff --git a/deployments/1287_moonbase_alpha/LaunchpoolLibrary.json b/deployments/1287_moonbase_alpha/LaunchpoolLibrary.json new file mode 100644 index 0000000..06b2aee --- /dev/null +++ b/deployments/1287_moonbase_alpha/LaunchpoolLibrary.json @@ -0,0 +1,12 @@ +[ + { + "name": "LaunchpoolLibrary", + "type": "library", + "address": "0xe7F3843639DFFd610176327C5Eb5220F44a5cF9C", + "commitHash": "9848e7ea8ed443e43199159f60c365f9cc7b883e", + "deploymentTime": "2025-04-13T13:49:43.673Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "version": "v1", + "isUpgradeSafe": true + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/MockNativeToken.json b/deployments/1287_moonbase_alpha/MockNativeToken.json new file mode 100644 index 0000000..1e55ec5 --- /dev/null +++ b/deployments/1287_moonbase_alpha/MockNativeToken.json @@ -0,0 +1,12 @@ +[ + { + "name": "MockNativeToken", + "type": "contract", + "address": "0x7a4ebae8cA815b9F52F23a8AC9A2f707D4d4ff81", + "deploymentTime": "2025-04-07T10:22:01.516Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "commitHash": "cd2af1e252bc4392e969fba85c56ed6d9784f88d", + "version": "v1", + "isUpgradeSafe": false + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/MockProjectToken.json b/deployments/1287_moonbase_alpha/MockProjectToken.json new file mode 100644 index 0000000..2f42f0e --- /dev/null +++ b/deployments/1287_moonbase_alpha/MockProjectToken.json @@ -0,0 +1,12 @@ +[ + { + "name": "MockProjectToken", + "type": "contract", + "address": "0x96b6D28DF53641A47be72F44BE8C626bf07365A8", + "deploymentTime": "2025-04-07T10:22:07.290Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "commitHash": "cd2af1e252bc4392e969fba85c56ed6d9784f88d", + "version": "v1", + "isUpgradeSafe": false + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/MockVToken.json b/deployments/1287_moonbase_alpha/MockVToken.json new file mode 100644 index 0000000..34ef378 --- /dev/null +++ b/deployments/1287_moonbase_alpha/MockVToken.json @@ -0,0 +1,12 @@ +[ + { + "name": "MockVToken", + "type": "contract", + "address": "0xD02D73E05b002Cb8EB7BEf9DF8Ed68ed39752465", + "deploymentTime": "2025-04-07T10:21:54.950Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "commitHash": "cd2af1e252bc4392e969fba85c56ed6d9784f88d", + "version": "v1", + "isUpgradeSafe": false + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/MockXCMOracle.json b/deployments/1287_moonbase_alpha/MockXCMOracle.json new file mode 100644 index 0000000..defd9e0 --- /dev/null +++ b/deployments/1287_moonbase_alpha/MockXCMOracle.json @@ -0,0 +1,18 @@ +[ + { + "name": "MockXCMOracle", + "type": "contract", + "address": "0x288154C87Db809bc0d702CB46De40E5041b22071", + "commitHash": "9848e7ea8ed443e43199159f60c365f9cc7b883e", + "deploymentTime": "2025-04-13T13:45:07.611Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "version": "v1", + "isUpgradeSafe": false, + "constructorArgs": { + "_initialRate": "1000000000000000000", + "_blockInterval": "10", + "_apy": "100000", + "_networkBlockTime": 6 + } + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/ProjectHubUpgradable.json b/deployments/1287_moonbase_alpha/ProjectHubUpgradable.json new file mode 100644 index 0000000..b821a9e --- /dev/null +++ b/deployments/1287_moonbase_alpha/ProjectHubUpgradable.json @@ -0,0 +1,32 @@ +[ + { + "name": "ProjectHubUpgradable", + "type": "contract", + "address": "0x2116404EaFDb0416BB99c09EC855f46F9b5173fE", + "commitHash": "9848e7ea8ed443e43199159f60c365f9cc7b883e", + "deploymentTime": "2025-04-13T13:51:31.773Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "version": "v1", + "linkedLibraries": { + "ProjectLibrary": "0x8BDB2E6F6dD2172178BCba5529C3D5dFe96B1538", + "LaunchpoolLibrary": "0xe7F3843639DFFd610176327C5Eb5220F44a5cF9C" + }, + "isUpgradeSafe": true, + "upgradeability": { + "pattern": "transparent", + "proxyAddress": "0xD1b11fE68a7e363E5564aB86AB496Ec9C4eB125d", + "proxyAdminAddress": "0xA2Dc035516B9Ae2DeCB18753599A82cb802fa4D4", + "implementationAddress": "0x2116404EaFDb0416BB99c09EC855f46F9b5173fE", + "initializerArgs": { + "_xcmOracleAddress": "0x288154C87Db809bc0d702CB46De40E5041b22071", + "_initialOwner": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "_initialVAssets": [ + "0xD02D73E05b002Cb8EB7BEf9DF8Ed68ed39752465" + ], + "_initialNativeAssets": [ + "0x7a4ebae8cA815b9F52F23a8AC9A2f707D4d4ff81" + ] + } + } + } +] \ No newline at end of file diff --git a/deployments/1287_moonbase_alpha/ProjectLibrary.json b/deployments/1287_moonbase_alpha/ProjectLibrary.json new file mode 100644 index 0000000..f16f0a9 --- /dev/null +++ b/deployments/1287_moonbase_alpha/ProjectLibrary.json @@ -0,0 +1,12 @@ +[ + { + "name": "ProjectLibrary", + "type": "library", + "address": "0x8BDB2E6F6dD2172178BCba5529C3D5dFe96B1538", + "commitHash": "9848e7ea8ed443e43199159f60c365f9cc7b883e", + "deploymentTime": "2025-04-13T13:49:37.945Z", + "deployer": "0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27", + "version": "v1", + "isUpgradeSafe": true + } +] \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index cfa2060..0e35c14 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,5 +3,9 @@ solc_version = "0.8.26" src = "src" out = "out" libs = ["lib"] +ffi = true # Enables Foreign Function Interface, allowing calls to external processes or scripts +ast = true # Outputs the Abstract Syntax Tree for your Solidity contracts. +build_info = true # Generates additional build information for your contracts. +extra_output = ["storageLayout"] # Outputs the storage layout information for your contracts. # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/git b/git new file mode 100644 index 0000000..e69de29 diff --git a/hardhat.config.ts b/hardhat.config.ts new file mode 100644 index 0000000..31a3cdc --- /dev/null +++ b/hardhat.config.ts @@ -0,0 +1,101 @@ +import "@nomicfoundation/hardhat-toolbox"; +import "@nomicfoundation/hardhat-foundry"; +import "@openzeppelin/hardhat-upgrades"; +import "hardhat-preprocessor"; +import "@typechain/hardhat"; +import { HardhatUserConfig } from "hardhat/types"; +import * as fs from "node:fs"; +import "dotenv/config"; + +// Parse env variables +const privateKeys = (process.env.PRIVATE_KEYS || "").split(","); +const devPrivateKeys = [ + // "3f5c38d6e87a9a91f4ddc80f6f57bc8bbbe59619911c01d5a47003a1a79117bd", // Inject Minh EVM for testing + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", +]; + +function getRemappings() { + return fs + .readFileSync("remappings.txt", "utf8") + .split("\n") + .filter(Boolean) // remove empty lines + .map((line: string) => line.trim().split("=")); +} + +// Export config +const config: HardhatUserConfig = { + defaultNetwork: "localhost", + networks: { + localhost: { + url: "http://localhost:8545", + accounts: devPrivateKeys, + loggingEnabled: true, + }, + sepolia: { + url: "https://eth-sepolia.g.alchemy.com/v2/vmbHGNAV4NKw9V2tleUXODo4NDDUQpiy", + accounts: privateKeys, + loggingEnabled: true, + }, + moonbase_alpha: { + url: "https://rpc.api.moonbase.moonbeam.network", + accounts: privateKeys, + loggingEnabled: true, + }, + }, + solidity: { + version: "0.8.26", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + paths: { + sources: "./src", + tests: "./test-hardhat", + cache: "./cache-hardhat", + artifacts: "./out-hardhat", + }, + + mocha: { + timeout: 40000, + }, + + // Advanced configs + typechain: { + outDir: "typechain-types", + target: "ethers-v6", + alwaysGenerateOverloads: true, + externalArtifacts: ["./artifacts/*.json"], + }, + + // Adapt to foundry's remappings in remappings.txt + preprocess: { + eachLine: (hre) => ({ + transform: (line: string) => { + if (line.match(/".*.sol";$/)) { + // match all lines with `".sol";` + for (const [from, to] of getRemappings()) { + if (line.includes(from)) { + line = line.replace(from, to); + break; + } + } + } + return line; + }, + }), + }, +}; + +export default config; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index c9ed45b..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6261 +0,0 @@ -{ - "name": "Defrost-Contracts", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "devDependencies": { - "@commitlint/cli": "^19.7.1", - "@commitlint/config-conventional": "^19.7.1", - "@nomiclabs/hardhat-solhint": "^4.0.1", - "husky": "^9.0.0", - "lint-staged": "^15.4.3", - "prettier": "^3.5.0", - "prettier-plugin-solidity": "^1.4.2", - "solhint-plugin-prettier": "^0.1.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@commitlint/cli": { - "version": "19.7.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.7.1.tgz", - "integrity": "sha512-iObGjR1tE/PfDtDTEfd+tnRkB3/HJzpQqRTyofS2MPPkDn1mp3DBC8SoPDayokfAy+xKhF8+bwRCJO25Nea0YQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/format": "^19.5.0", - "@commitlint/lint": "^19.7.1", - "@commitlint/load": "^19.6.1", - "@commitlint/read": "^19.5.0", - "@commitlint/types": "^19.5.0", - "tinyexec": "^0.3.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@commitlint/cli/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@commitlint/cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "19.7.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.7.1.tgz", - "integrity": "sha512-fsEIF8zgiI/FIWSnykdQNj/0JE4av08MudLTyYHm4FlLWemKoQvPNUYU2M/3tktWcCEyq7aOkDDgtjrmgWFbvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "conventional-changelog-conventionalcommits": "^7.0.2" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.5.0.tgz", - "integrity": "sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator/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/@commitlint/config-validator/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/@commitlint/ensure": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.5.0.tgz", - "integrity": "sha512-Kv0pYZeMrdg48bHFEU5KKcccRfKmISSm9MvgIgkpI6m+ohFTB55qZlBW6eYqh/XDfRuIO0x4zSmvBjmOwWTwkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/execute-rule": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.5.0.tgz", - "integrity": "sha512-aqyGgytXhl2ejlk+/rfgtwpPexYyri4t8/n4ku6rRJoRhGZpLFMqrZ+YaubeGysCP6oz4mMA34YSTaSOKEeNrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.5.0.tgz", - "integrity": "sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "chalk": "^5.3.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "19.7.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.7.1.tgz", - "integrity": "sha512-3IaOc6HVg2hAoGleRK3r9vL9zZ3XY0rf1RsUf6jdQLuaD46ZHnXBiOPTyQ004C4IvYjSWqJwlh0/u2P73aIE3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "semver": "^7.6.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/is-ignored/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@commitlint/lint": { - "version": "19.7.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.7.1.tgz", - "integrity": "sha512-LhcPfVjcOcOZA7LEuBBeO00o3MeZa+tWrX9Xyl1r9PMd5FWsEoZI9IgnGqTKZ0lZt5pO3ZlstgnRyY1CJJc9Xg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/is-ignored": "^19.7.1", - "@commitlint/parse": "^19.5.0", - "@commitlint/rules": "^19.6.0", - "@commitlint/types": "^19.5.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load": { - "version": "19.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.6.1.tgz", - "integrity": "sha512-kE4mRKWWNju2QpsCWt428XBvUH55OET2N4QKQ0bF85qS/XbsRGG1MiTByDNlEVpEPceMkDr46LNH95DtRwcsfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^19.5.0", - "@commitlint/execute-rule": "^19.5.0", - "@commitlint/resolve-extends": "^19.5.0", - "@commitlint/types": "^19.5.0", - "chalk": "^5.3.0", - "cosmiconfig": "^9.0.0", - "cosmiconfig-typescript-loader": "^6.1.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.1.0.tgz", - "integrity": "sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jiti": "^2.4.1" - }, - "engines": { - "node": ">=v18" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=9", - "typescript": ">=5" - } - }, - "node_modules/@commitlint/message": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.5.0.tgz", - "integrity": "sha512-R7AM4YnbxN1Joj1tMfCyBryOC5aNJBdxadTZkuqtWi3Xj0kMdutq16XQwuoGbIzL2Pk62TALV1fZDCv36+JhTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.5.0.tgz", - "integrity": "sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^19.5.0", - "conventional-changelog-angular": "^7.0.0", - "conventional-commits-parser": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/read": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.5.0.tgz", - "integrity": "sha512-TjS3HLPsLsxFPQj6jou8/CZFAmOP2y+6V4PGYt3ihbQKTY1Jnv0QG28WRKl/d1ha6zLODPZqsxLEov52dhR9BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/top-level": "^19.5.0", - "@commitlint/types": "^19.5.0", - "git-raw-commits": "^4.0.0", - "minimist": "^1.2.8", - "tinyexec": "^0.3.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.5.0.tgz", - "integrity": "sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^19.5.0", - "@commitlint/types": "^19.5.0", - "global-directory": "^4.0.1", - "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/rules": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.6.0.tgz", - "integrity": "sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/ensure": "^19.5.0", - "@commitlint/message": "^19.5.0", - "@commitlint/to-lines": "^19.5.0", - "@commitlint/types": "^19.5.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.5.0.tgz", - "integrity": "sha512-R772oj3NHPkodOSRZ9bBVNq224DOxQtNef5Pl8l2M8ZnkkzQfeSTr4uxawV2Sd3ui05dUVzvLNnzenDBO1KBeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.5.0.tgz", - "integrity": "sha512-IP1YLmGAk0yWrImPRRc578I3dDUI5A2UBJx9FbSOjxe9sTlzFiwVJ+zeMLgAtHMtGZsC8LUnzmW1qRemkFU4ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^7.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level/node_modules/find-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", - "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^7.2.0", - "path-exists": "^5.0.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/top-level/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/top-level/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/top-level/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/top-level/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/@commitlint/top-level/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@commitlint/types": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.5.0.tgz", - "integrity": "sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/conventional-commits-parser": "^5.0.0", - "chalk": "^5.3.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "peer": true, - "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" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "dev": true, - "license": "ISC", - "peer": true, - "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" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "peer": true - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "peer": true - }, - "node_modules/@nomicfoundation/edr": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.7.0.tgz", - "integrity": "sha512-+Zyu7TE47TGNcPhOfWLPA/zISs32WDMXrhSWdWYyPHDVn/Uux5TVuOeScKb0BR/R8EJ+leR8COUF/EGxvDOVKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.7.0", - "@nomicfoundation/edr-darwin-x64": "0.7.0", - "@nomicfoundation/edr-linux-arm64-gnu": "0.7.0", - "@nomicfoundation/edr-linux-arm64-musl": "0.7.0", - "@nomicfoundation/edr-linux-x64-gnu": "0.7.0", - "@nomicfoundation/edr-linux-x64-musl": "0.7.0", - "@nomicfoundation/edr-win32-x64-msvc": "0.7.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.7.0.tgz", - "integrity": "sha512-vAH20oh4GaSB/iQFTRcoO8jLc0CLd9XuLY9I7vtcqZWAiM4U1J4Y8cu67PWmtxbvUQOqXR7S6FtAr8/AlWm14g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.7.0.tgz", - "integrity": "sha512-WHDdIrPvLlgXQr2eKypBM5xOZAwdxhDAEQIvEMQL8tEEm2qYW2bliUlssBPrs8E3bdivFbe1HizImslMAfU3+g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.7.0.tgz", - "integrity": "sha512-WXpJB54ukz1no7gxCPXVEw9pgl/9UZ/WO3l1ctyv/T7vOygjqA4SUd6kppTs6MNXAuTiisPtvJ/fmvHiMBLrsw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.7.0.tgz", - "integrity": "sha512-1iZYOcEgc+zJI7JQrlAFziuy9sBz1WgnIx3HIIu0J7lBRZ/AXeHHgATb+4InqxtEx9O3W8A0s7f11SyFqJL4Aw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.7.0.tgz", - "integrity": "sha512-wSjC94WcR5MM8sg9w3OsAmT6+bbmChJw6uJKoXR3qscps/jdhjzJWzfgT0XGRq3XMUfimyafW2RWOyfX3ouhrQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.7.0.tgz", - "integrity": "sha512-Us22+AZ7wkG1mZwxqE4S4ZcuwkEA5VrUiBOJSvKHGOgy6vFvB/Euh5Lkp4GovwjrtiXuvyGO2UmtkzymZKDxZw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.7.0.tgz", - "integrity": "sha512-HAry0heTsWkzReVtjHwoIq3BgFCvXpVhJ5qPmTnegZGsr/KxqvMmHyDMifzKao4bycU8yrpTSyOiAJt27RWjzQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", - "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.4" - } - }, - "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", - "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", - "dev": true, - "license": "MPL-2.0", - "peer": true, - "bin": { - "rlp": "bin/rlp.cjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", - "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", - "dev": true, - "license": "MPL-2.0", - "peer": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } - } - }, - "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "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.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", - "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", - "dev": true, - "license": "MPL-2.0", - "peer": true, - "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "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.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", - "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 12" - }, - "optionalDependencies": { - "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", - "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", - "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", - "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", - "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", - "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", - "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", - "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", - "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomiclabs/hardhat-solhint": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-solhint/-/hardhat-solhint-4.0.1.tgz", - "integrity": "sha512-ekfbbGfUwMZGr9aPAurPa7GVMX/6XqKemppVEez+mC36H7G5UyBsnrUKZMhMDVHG9S7+ke9sLuaibnWvpdSrQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "solhint": "^5.0.2" - }, - "peerDependencies": { - "hardhat": "^2.0.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/network.ca-file/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/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "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/@prettier/sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.3.0.tgz", - "integrity": "sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/prettier/prettier-synchronized?sponsor=1" - }, - "peerDependencies": { - "prettier": "^3.0.0" - } - }, - "node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "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.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "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.19.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", - "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", - "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/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/conventional-commits-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", - "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true, - "license": "MIT" - }, - "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/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "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/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "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/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "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/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "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/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/dargs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", - "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "deprecated": "This library has been deprecated and usage is discouraged.", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "license": "MPL-2.0", - "peer": true, - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-util/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "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.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true, - "license": "MIT" - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "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/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "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/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/git-raw-commits": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", - "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dargs": "^8.0.0", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "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/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-directory/node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "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.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/hardhat": { - "version": "2.22.18", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.18.tgz", - "integrity": "sha512-2+kUz39gvMo56s75cfLBhiFedkQf+gXdrwCcz4R/5wW0oBdwiyfj2q9BIkMoaA0WIGYYMU2I1Cc4ucTunhfjzw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.7.0", - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-tx": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "@nomicfoundation/solidity-analyzer": "^0.1.0", - "@sentry/node": "^5.18.1", - "@types/bn.js": "^5.1.0", - "@types/lru-cache": "^5.1.0", - "adm-zip": "^0.4.16", - "aggregate-error": "^3.0.0", - "ansi-escapes": "^4.3.0", - "boxen": "^5.1.2", - "chokidar": "^4.0.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "ethereum-cryptography": "^1.0.3", - "ethereumjs-abi": "^0.6.8", - "find-up": "^5.0.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "immutable": "^4.0.0-rc.12", - "io-ts": "1.10.4", - "json-stream-stringify": "^3.1.4", - "keccak": "^3.0.2", - "lodash": "^4.17.11", - "mnemonist": "^0.38.0", - "mocha": "^10.0.0", - "p-map": "^4.0.0", - "picocolors": "^1.1.0", - "raw-body": "^2.4.1", - "resolve": "1.17.0", - "semver": "^6.3.0", - "solc": "0.8.26", - "source-map-support": "^0.5.13", - "stacktrace-parser": "^0.1.10", - "tinyglobby": "^0.2.6", - "tsort": "0.0.1", - "undici": "^5.14.0", - "uuid": "^8.3.2", - "ws": "^7.4.6" - }, - "bin": { - "hardhat": "internal/cli/bootstrap.js" - }, - "peerDependencies": { - "ts-node": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "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/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", - "dev": true, - "license": "MIT", - "bin": { - "husky": "bin.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.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/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "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/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fp-ts": "^1.0.0" - } - }, - "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-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "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/json-stream-stringify": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", - "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=7.10.1" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.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/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "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/lint-staged": { - "version": "15.4.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", - "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.4.1", - "commander": "^13.1.0", - "debug": "^4.4.0", - "execa": "^8.0.1", - "lilconfig": "^3.1.3", - "listr2": "^8.2.5", - "micromatch": "^4.0.8", - "pidtree": "^0.6.0", - "string-argv": "^0.3.2", - "yaml": "^2.7.0" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "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/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "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/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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/mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "obliterator": "^2.0.0" - } - }, - "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/obliterator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", - "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/package-json/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "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/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "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/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "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": "3.5.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.0.tgz", - "integrity": "sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/prettier-plugin-solidity": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.2.tgz", - "integrity": "sha512-VVD/4XlDjSzyPWWCPW8JEleFa8JNKFYac5kNlMjVXemQyQZKfpekPMhFZSePuXB6L+RixlFvWe20iacGjFYrLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@solidity-parser/parser": "^0.19.0", - "semver": "^7.6.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "prettier": ">=2.3.0" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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/rc/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/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", - "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/registry-auth-token": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", - "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "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-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", - "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "dev": true, - "license": "MPL-2.0", - "peer": true, - "dependencies": { - "bn.js": "^5.2.0" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/secp256k1/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/secp256k1/node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/secp256k1/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "license": "(MIT AND BSD-3-Clause)", - "peer": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/solc": { - "version": "0.8.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", - "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solc.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/solhint": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.5.tgz", - "integrity": "sha512-WrnG6T+/UduuzSWsSOAbfq1ywLUDwNea3Gd5hg6PS+pLUm8lz2ECNr0beX609clBxmDeZ3676AiA9nPDljmbJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@solidity-parser/parser": "^0.19.0", - "ajv": "^6.12.6", - "antlr4": "^4.13.1-patch-1", - "ast-parents": "^0.0.1", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "cosmiconfig": "^8.0.0", - "fast-diff": "^1.2.0", - "glob": "^8.0.3", - "ignore": "^5.2.4", - "js-yaml": "^4.1.0", - "latest-version": "^7.0.0", - "lodash": "^4.17.21", - "pluralize": "^8.0.0", - "semver": "^7.5.2", - "strip-ansi": "^6.0.1", - "table": "^6.8.1", - "text-table": "^0.2.0" - }, - "bin": { - "solhint": "solhint.js" - }, - "optionalDependencies": { - "prettier": "^2.8.3" - } - }, - "node_modules/solhint-plugin-prettier": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/solhint-plugin-prettier/-/solhint-plugin-prettier-0.1.0.tgz", - "integrity": "sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@prettier/sync": "^0.3.0", - "prettier-linter-helpers": "^1.0.0" - }, - "peerDependencies": { - "prettier": "^3.0.0", - "prettier-plugin-solidity": "^1.0.0" - } - }, - "node_modules/solhint/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/solhint/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/solhint/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.19" - } - }, - "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-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fdir": "^6.4.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD", - "peer": true - }, - "node_modules/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true, - "license": "Unlicense", - "peer": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true, - "license": "Unlicense", - "peer": true - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", - "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "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/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true, - "license": "Apache-2.0", - "peer": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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" - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "license": "MIT", - "peer": true, - "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 - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json index e07d656..30bbcbb 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,43 @@ { - "dependencies": { - }, "devDependencies": { - "@nomiclabs/hardhat-solhint": "^4.0.1", "@commitlint/cli": "^19.7.1", "@commitlint/config-conventional": "^19.7.1", + "@nomicfoundation/hardhat-ethers": "^3.0.8", + "@nomicfoundation/hardhat-foundry": "^1.1.3", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@nomiclabs/hardhat-solhint": "^4.0.1", + "@openzeppelin/hardhat-upgrades": "^3.9.0", + "@openzeppelin/upgrades-core": "^1.42.1", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", + "dotenv": "^16.4.7", + "ethers": "^6.13.5", + "hardhat": "^2.22.19", + "hardhat-preprocessor": "^0.1.5", "husky": "^9.0.0", "lint-staged": "^15.4.3", "prettier": "^3.5.0", "prettier-plugin-solidity": "^1.4.2", - "solhint-plugin-prettier": "^0.1.0" + "solhint-plugin-prettier": "^0.1.0", + "typechain": "^8.3.2" }, "lint-staged": { - "*.sol": [ + "src/**/*.sol": [ "prettier --write --plugin=prettier-plugin-solidity", "solhint" + ], + "test/**/*.sol": [ + "prettier --write --plugin=prettier-plugin-solidity" + ], + "script/**/*.sol": [ + "prettier --write --plugin=prettier-plugin-solidity" ] }, "scripts": { - "prepare": "husky install", + "prepare": "husky", "lint": "solhint 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", "lint:fix": "solhint 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol' --fix --noPrompt", "format:sol": "prettier --write * --plugin=prettier-plugin-solidity" - } + }, + "packageManager": "pnpm@10.4.0+sha512.6b849d0787d97f8f4e1f03a9b8ff8f038e79e153d6f11ae539ae7c435ff9e796df6a862c991502695c7f9e8fac8aeafc1ac5a8dab47e36148d183832d886dd52" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..e3d0249 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7186 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@commitlint/cli': + specifier: ^19.7.1 + version: 19.7.1(@types/node@22.13.9)(typescript@5.8.2) + '@commitlint/config-conventional': + specifier: ^19.7.1 + version: 19.7.1 + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.8 + version: 3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-foundry': + specifier: ^1.1.3 + version: 1.1.3(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-toolbox': + specifier: ^5.0.0 + version: 5.0.0(0e7772daf0a8bbd3d2fcd6fbe17c525b) + '@nomiclabs/hardhat-solhint': + specifier: ^4.0.1 + version: 4.0.1(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))(typescript@5.8.2) + '@openzeppelin/hardhat-upgrades': + specifier: ^3.9.0 + version: 3.9.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@openzeppelin/upgrades-core': + specifier: ^1.42.1 + version: 1.42.1 + '@typechain/ethers-v6': + specifier: ^0.5.1 + version: 0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2) + '@typechain/hardhat': + specifier: ^9.1.0 + version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2))(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))(typechain@8.3.2(typescript@5.8.2)) + dotenv: + specifier: ^16.4.7 + version: 16.4.7 + ethers: + specifier: ^6.13.5 + version: 6.13.5 + hardhat: + specifier: ^2.22.19 + version: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + hardhat-preprocessor: + specifier: ^0.1.5 + version: 0.1.5(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + husky: + specifier: ^9.0.0 + version: 9.1.7 + lint-staged: + specifier: ^15.4.3 + version: 15.4.3 + prettier: + specifier: ^3.5.0 + version: 3.5.3 + prettier-plugin-solidity: + specifier: ^1.4.2 + version: 1.4.2(prettier@3.5.3) + solhint-plugin-prettier: + specifier: ^0.1.0 + version: 0.1.0(prettier-plugin-solidity@1.4.2(prettier@3.5.3))(prettier@3.5.3) + typechain: + specifier: ^8.3.2 + version: 8.3.2(typescript@5.8.2) + +packages: + + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@1.2.2': + resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@1.2.2': + resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-lambda@3.758.0': + resolution: {integrity: sha512-k7L9fe0NN1v2Vhg4ofA1pb26gTdGVFdkA6XUQyElLEdcKzJzoYiQ60faNLuMPfH0zsKNvy/xKfNOD6DFZWjgEg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.758.0': + resolution: {integrity: sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.758.0': + resolution: {integrity: sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.758.0': + resolution: {integrity: sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.758.0': + resolution: {integrity: sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.758.0': + resolution: {integrity: sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.758.0': + resolution: {integrity: sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.758.0': + resolution: {integrity: sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.758.0': + resolution: {integrity: sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.758.0': + resolution: {integrity: sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.734.0': + resolution: {integrity: sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.734.0': + resolution: {integrity: sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.734.0': + resolution: {integrity: sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.758.0': + resolution: {integrity: sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/nested-clients@3.758.0': + resolution: {integrity: sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/region-config-resolver@3.734.0': + resolution: {integrity: sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.758.0': + resolution: {integrity: sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.734.0': + resolution: {integrity: sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.743.0': + resolution: {integrity: sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.723.0': + resolution: {integrity: sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.734.0': + resolution: {integrity: sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==} + + '@aws-sdk/util-user-agent-node@3.758.0': + resolution: {integrity: sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@bytecodealliance/preview2-shim@0.17.0': + resolution: {integrity: sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ==} + + '@commitlint/cli@19.7.1': + resolution: {integrity: sha512-iObGjR1tE/PfDtDTEfd+tnRkB3/HJzpQqRTyofS2MPPkDn1mp3DBC8SoPDayokfAy+xKhF8+bwRCJO25Nea0YQ==} + engines: {node: '>=v18'} + hasBin: true + + '@commitlint/config-conventional@19.7.1': + resolution: {integrity: sha512-fsEIF8zgiI/FIWSnykdQNj/0JE4av08MudLTyYHm4FlLWemKoQvPNUYU2M/3tktWcCEyq7aOkDDgtjrmgWFbvg==} + engines: {node: '>=v18'} + + '@commitlint/config-validator@19.5.0': + resolution: {integrity: sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==} + engines: {node: '>=v18'} + + '@commitlint/ensure@19.5.0': + resolution: {integrity: sha512-Kv0pYZeMrdg48bHFEU5KKcccRfKmISSm9MvgIgkpI6m+ohFTB55qZlBW6eYqh/XDfRuIO0x4zSmvBjmOwWTwkg==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@19.5.0': + resolution: {integrity: sha512-aqyGgytXhl2ejlk+/rfgtwpPexYyri4t8/n4ku6rRJoRhGZpLFMqrZ+YaubeGysCP6oz4mMA34YSTaSOKEeNrg==} + engines: {node: '>=v18'} + + '@commitlint/format@19.5.0': + resolution: {integrity: sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@19.7.1': + resolution: {integrity: sha512-3IaOc6HVg2hAoGleRK3r9vL9zZ3XY0rf1RsUf6jdQLuaD46ZHnXBiOPTyQ004C4IvYjSWqJwlh0/u2P73aIE3g==} + engines: {node: '>=v18'} + + '@commitlint/lint@19.7.1': + resolution: {integrity: sha512-LhcPfVjcOcOZA7LEuBBeO00o3MeZa+tWrX9Xyl1r9PMd5FWsEoZI9IgnGqTKZ0lZt5pO3ZlstgnRyY1CJJc9Xg==} + engines: {node: '>=v18'} + + '@commitlint/load@19.6.1': + resolution: {integrity: sha512-kE4mRKWWNju2QpsCWt428XBvUH55OET2N4QKQ0bF85qS/XbsRGG1MiTByDNlEVpEPceMkDr46LNH95DtRwcsfA==} + engines: {node: '>=v18'} + + '@commitlint/message@19.5.0': + resolution: {integrity: sha512-R7AM4YnbxN1Joj1tMfCyBryOC5aNJBdxadTZkuqtWi3Xj0kMdutq16XQwuoGbIzL2Pk62TALV1fZDCv36+JhTQ==} + engines: {node: '>=v18'} + + '@commitlint/parse@19.5.0': + resolution: {integrity: sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==} + engines: {node: '>=v18'} + + '@commitlint/read@19.5.0': + resolution: {integrity: sha512-TjS3HLPsLsxFPQj6jou8/CZFAmOP2y+6V4PGYt3ihbQKTY1Jnv0QG28WRKl/d1ha6zLODPZqsxLEov52dhR9BQ==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@19.5.0': + resolution: {integrity: sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==} + engines: {node: '>=v18'} + + '@commitlint/rules@19.6.0': + resolution: {integrity: sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@19.5.0': + resolution: {integrity: sha512-R772oj3NHPkodOSRZ9bBVNq224DOxQtNef5Pl8l2M8ZnkkzQfeSTr4uxawV2Sd3ui05dUVzvLNnzenDBO1KBeQ==} + engines: {node: '>=v18'} + + '@commitlint/top-level@19.5.0': + resolution: {integrity: sha512-IP1YLmGAk0yWrImPRRc578I3dDUI5A2UBJx9FbSOjxe9sTlzFiwVJ+zeMLgAtHMtGZsC8LUnzmW1qRemkFU4ng==} + engines: {node: '>=v18'} + + '@commitlint/types@19.5.0': + resolution: {integrity: sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==} + engines: {node: '>=v18'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@ethereumjs/rlp@4.0.1': + resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} + engines: {node: '>=14'} + hasBin: true + + '@ethereumjs/util@8.1.0': + resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} + engines: {node: '>=14'} + + '@ethersproject/abi@5.8.0': + resolution: {integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==} + + '@ethersproject/abstract-provider@5.8.0': + resolution: {integrity: sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==} + + '@ethersproject/abstract-signer@5.8.0': + resolution: {integrity: sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==} + + '@ethersproject/address@5.6.1': + resolution: {integrity: sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==} + + '@ethersproject/address@5.8.0': + resolution: {integrity: sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==} + + '@ethersproject/base64@5.8.0': + resolution: {integrity: sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==} + + '@ethersproject/basex@5.8.0': + resolution: {integrity: sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==} + + '@ethersproject/bignumber@5.8.0': + resolution: {integrity: sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==} + + '@ethersproject/bytes@5.8.0': + resolution: {integrity: sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==} + + '@ethersproject/constants@5.8.0': + resolution: {integrity: sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==} + + '@ethersproject/contracts@5.8.0': + resolution: {integrity: sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==} + + '@ethersproject/hash@5.8.0': + resolution: {integrity: sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==} + + '@ethersproject/hdnode@5.8.0': + resolution: {integrity: sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==} + + '@ethersproject/json-wallets@5.8.0': + resolution: {integrity: sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==} + + '@ethersproject/keccak256@5.8.0': + resolution: {integrity: sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==} + + '@ethersproject/logger@5.8.0': + resolution: {integrity: sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==} + + '@ethersproject/networks@5.8.0': + resolution: {integrity: sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==} + + '@ethersproject/pbkdf2@5.8.0': + resolution: {integrity: sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==} + + '@ethersproject/properties@5.8.0': + resolution: {integrity: sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==} + + '@ethersproject/providers@5.8.0': + resolution: {integrity: sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==} + + '@ethersproject/random@5.8.0': + resolution: {integrity: sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==} + + '@ethersproject/rlp@5.8.0': + resolution: {integrity: sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==} + + '@ethersproject/sha2@5.8.0': + resolution: {integrity: sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==} + + '@ethersproject/signing-key@5.8.0': + resolution: {integrity: sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==} + + '@ethersproject/solidity@5.8.0': + resolution: {integrity: sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==} + + '@ethersproject/strings@5.8.0': + resolution: {integrity: sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==} + + '@ethersproject/transactions@5.8.0': + resolution: {integrity: sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==} + + '@ethersproject/units@5.8.0': + resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==} + + '@ethersproject/wallet@5.8.0': + resolution: {integrity: sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==} + + '@ethersproject/web@5.8.0': + resolution: {integrity: sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==} + + '@ethersproject/wordlists@5.8.0': + resolution: {integrity: sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@metamask/eth-sig-util@4.0.1': + resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} + engines: {node: '>=12.0.0'} + + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/curves@1.4.2': + resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} + + '@noble/hashes@1.2.0': + resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/secp256k1@1.7.1': + resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nomicfoundation/edr-darwin-arm64@0.8.0': + resolution: {integrity: sha512-sKTmOu/P5YYhxT0ThN2Pe3hmCE/5Ag6K/eYoiavjLWbR7HEb5ZwPu2rC3DpuUk1H+UKJqt7o4/xIgJxqw9wu6A==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-darwin-x64@0.8.0': + resolution: {integrity: sha512-8ymEtWw1xf1Id1cc42XIeE+9wyo3Dpn9OD/X8GiaMz9R70Ebmj2g+FrbETu8o6UM+aL28sBZQCiCzjlft2yWAg==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-arm64-gnu@0.8.0': + resolution: {integrity: sha512-h/wWzS2EyQuycz+x/SjMRbyA+QMCCVmotRsgM1WycPARvVZWIVfwRRsKoXKdCftsb3S8NTprqBdJlOmsFyETFA==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-arm64-musl@0.8.0': + resolution: {integrity: sha512-gnWxDgdkka0O9GpPX/gZT3REeKYV28Guyg13+Vj/bbLpmK1HmGh6Kx+fMhWv+Ht/wEmGDBGMCW1wdyT/CftJaQ==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-x64-gnu@0.8.0': + resolution: {integrity: sha512-DTMiAkgAx+nyxcxKyxFZk1HPakXXUCgrmei7r5G7kngiggiGp/AUuBBWFHi8xvl2y04GYhro5Wp+KprnLVoAPA==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-x64-musl@0.8.0': + resolution: {integrity: sha512-iTITWe0Zj8cNqS0xTblmxPbHVWwEtMiDC+Yxwr64d7QBn/1W0ilFQ16J8gB6RVVFU3GpfNyoeg3tUoMpSnrm6Q==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-win32-x64-msvc@0.8.0': + resolution: {integrity: sha512-mNRDyd/C3j7RMcwapifzv2K57sfA5xOw8g2U84ZDvgSrXVXLC99ZPxn9kmolb+dz8VMm9FONTZz9ESS6v8DTnA==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr@0.8.0': + resolution: {integrity: sha512-dwWRrghSVBQDpt0wP+6RXD8BMz2i/9TI34TcmZqeEAZuCLei3U9KZRgGTKVAM1rMRvrpf5ROfPqrWNetKVUTag==} + engines: {node: '>= 18'} + + '@nomicfoundation/ethereumjs-common@4.0.4': + resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} + + '@nomicfoundation/ethereumjs-rlp@5.0.4': + resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} + engines: {node: '>=18'} + hasBin: true + + '@nomicfoundation/ethereumjs-tx@5.0.4': + resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/ethereumjs-util@9.0.4': + resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/hardhat-chai-matchers@2.0.8': + resolution: {integrity: sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + + '@nomicfoundation/hardhat-ethers@3.0.8': + resolution: {integrity: sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==} + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + + '@nomicfoundation/hardhat-foundry@1.1.3': + resolution: {integrity: sha512-30Ezc3hlZ4pC5Z/9W9euW5uoPKKQQKaecLETHJH8BPpd30zYOooy6HfjmcTY1/taOQjlwirOdNO7tHlje8Qcgw==} + peerDependencies: + hardhat: ^2.17.2 + + '@nomicfoundation/hardhat-ignition-ethers@0.15.10': + resolution: {integrity: sha512-P90glRiBbR4mnMKP/LePovfUJjYT2YWJjx7118i7yxssUwcaW9wFohb4bFh+236N1tqM4q7aGx9cBvHNgve3zA==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.4 + '@nomicfoundation/hardhat-ignition': ^0.15.10 + '@nomicfoundation/ignition-core': ^0.15.10 + ethers: ^6.7.0 + hardhat: ^2.18.0 + + '@nomicfoundation/hardhat-ignition@0.15.10': + resolution: {integrity: sha512-UScXyLLG5rEm+ANchQYCDOsskdXl6ux3oCPgC24PKE/QMJEib5crGZIo8spAyzdK6vOnRW6i4FG+1qvoO0AGWA==} + peerDependencies: + '@nomicfoundation/hardhat-verify': ^2.0.1 + hardhat: ^2.18.0 + + '@nomicfoundation/hardhat-network-helpers@1.0.12': + resolution: {integrity: sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==} + peerDependencies: + hardhat: ^2.9.5 + + '@nomicfoundation/hardhat-toolbox@5.0.0': + resolution: {integrity: sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==} + peerDependencies: + '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-ignition-ethers': ^0.15.0 + '@nomicfoundation/hardhat-network-helpers': ^1.0.0 + '@nomicfoundation/hardhat-verify': ^2.0.0 + '@typechain/ethers-v6': ^0.5.0 + '@typechain/hardhat': ^9.0.0 + '@types/chai': ^4.2.0 + '@types/mocha': '>=9.1.0' + '@types/node': '>=18.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.3.0 + typescript: '>=4.5.0' + + '@nomicfoundation/hardhat-verify@2.0.13': + resolution: {integrity: sha512-i57GX1sC0kYGyRVnbQrjjyBTpWTKgrvKC+jH8CMKV6gHp959Upb8lKaZ58WRHIU0espkulTxLnacYeUDirwJ2g==} + peerDependencies: + hardhat: ^2.0.4 + + '@nomicfoundation/ignition-core@0.15.10': + resolution: {integrity: sha512-AWvCviNlBkPT8EKcg34N+yUdQTYFiC/HdpfFZdw8oMFuAs9SMZE0zQA9gJQSCay41GbuyXt2Kietp5/1/nlBIA==} + + '@nomicfoundation/ignition-ui@0.15.10': + resolution: {integrity: sha512-82XQPF+1fvxTimDUPgDVwpTjHjfjFgFs84rERbBiMLQbz6sPtgTlV8HHrlbMx8tT/JKCI/SCU4gxV8xA4CPfcg==} + + '@nomicfoundation/slang@0.18.3': + resolution: {integrity: sha512-YqAWgckqbHM0/CZxi9Nlf4hjk9wUNLC9ngWCWBiqMxPIZmzsVKYuChdlrfeBPQyvQQBoOhbx+7C1005kLVQDZQ==} + + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': + resolution: {integrity: sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2': + resolution: {integrity: sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2': + resolution: {integrity: sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2': + resolution: {integrity: sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2': + resolution: {integrity: sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2': + resolution: {integrity: sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2': + resolution: {integrity: sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==} + engines: {node: '>= 12'} + + '@nomicfoundation/solidity-analyzer@0.1.2': + resolution: {integrity: sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==} + engines: {node: '>= 12'} + + '@nomiclabs/hardhat-solhint@4.0.1': + resolution: {integrity: sha512-ekfbbGfUwMZGr9aPAurPa7GVMX/6XqKemppVEez+mC36H7G5UyBsnrUKZMhMDVHG9S7+ke9sLuaibnWvpdSrQA==} + peerDependencies: + hardhat: ^2.0.0 + + '@openzeppelin/defender-sdk-base-client@2.4.0': + resolution: {integrity: sha512-oB18M3DNR/nREQhHLEXdcCsxv04DPbezBHzFz6APIez+MEpQQl2SwHYxA16vOyZ6A/zV0b8sFDqAjq0oogUMyA==} + + '@openzeppelin/defender-sdk-deploy-client@2.4.0': + resolution: {integrity: sha512-7brIWq7uW6ejYuxdBE6kQnZJQSF4v8g9Jed4/leXtPFjCowhDtIldhcYUfI+UPcZnDKdbvxnxXVJM2AWyVTNtQ==} + + '@openzeppelin/defender-sdk-network-client@2.4.0': + resolution: {integrity: sha512-+19/J7NiW7EC8yN3DbqA290JBzbdu1/iHpz9lE5RJ5YTPv50eReou0v7vZSBhKRN10P7AKM3V263W1zoVGpVdA==} + + '@openzeppelin/hardhat-upgrades@3.9.0': + resolution: {integrity: sha512-7YYBSxRnO/X+tsQkVgtz3/YbwZuQPjbjQ3m0A/8+vgQzdPfulR93NaFKgZfMonnrriXb5O/ULjIDPI+8nuqtyQ==} + hasBin: true + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^2.0.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + '@nomicfoundation/hardhat-verify': + optional: true + + '@openzeppelin/upgrades-core@1.42.1': + resolution: {integrity: sha512-8qnz2XfQrco8R8u9NjV+KiSLrVn7DnWFd+3BuhTUjhVy0bzCSu2SMKCVpZLtXbxf4f2dpz8jYPQYRa6s23PhLA==} + hasBin: true + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.3.1': + resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} + engines: {node: '>=12'} + + '@prettier/sync@0.3.0': + resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} + peerDependencies: + prettier: ^3.0.0 + + '@scure/base@1.1.9': + resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + + '@scure/bip32@1.1.5': + resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} + + '@scure/bip32@1.4.0': + resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} + + '@scure/bip39@1.1.1': + resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} + + '@scure/bip39@1.3.0': + resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + + '@sentry/core@5.30.0': + resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} + engines: {node: '>=6'} + + '@sentry/hub@5.30.0': + resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} + engines: {node: '>=6'} + + '@sentry/minimal@5.30.0': + resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} + engines: {node: '>=6'} + + '@sentry/node@5.30.0': + resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} + engines: {node: '>=6'} + + '@sentry/tracing@5.30.0': + resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} + engines: {node: '>=6'} + + '@sentry/types@5.30.0': + resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} + engines: {node: '>=6'} + + '@sentry/utils@5.30.0': + resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} + engines: {node: '>=6'} + + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + + '@smithy/abort-controller@4.0.1': + resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.0.1': + resolution: {integrity: sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.1.5': + resolution: {integrity: sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.0.1': + resolution: {integrity: sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.0.1': + resolution: {integrity: sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.0.1': + resolution: {integrity: sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.0.1': + resolution: {integrity: sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.0.1': + resolution: {integrity: sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.0.1': + resolution: {integrity: sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.0.1': + resolution: {integrity: sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.0.1': + resolution: {integrity: sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.0.1': + resolution: {integrity: sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.0.0': + resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.0.1': + resolution: {integrity: sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.0.6': + resolution: {integrity: sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.0.7': + resolution: {integrity: sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.0.2': + resolution: {integrity: sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.0.1': + resolution: {integrity: sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.0.1': + resolution: {integrity: sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.0.3': + resolution: {integrity: sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.0.1': + resolution: {integrity: sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.0.1': + resolution: {integrity: sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.0.1': + resolution: {integrity: sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.0.1': + resolution: {integrity: sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.0.1': + resolution: {integrity: sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.0.1': + resolution: {integrity: sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.0.1': + resolution: {integrity: sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.1.6': + resolution: {integrity: sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.1.0': + resolution: {integrity: sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.0.1': + resolution: {integrity: sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.0.0': + resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.0.0': + resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.0.0': + resolution: {integrity: sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.0.0': + resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.0.0': + resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.0.7': + resolution: {integrity: sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.0.7': + resolution: {integrity: sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.0.1': + resolution: {integrity: sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.0.0': + resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.0.1': + resolution: {integrity: sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.0.1': + resolution: {integrity: sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.1.2': + resolution: {integrity: sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.0.0': + resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.0.0': + resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.0.2': + resolution: {integrity: sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==} + engines: {node: '>=18.0.0'} + + '@solidity-parser/parser@0.14.5': + resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} + + '@solidity-parser/parser@0.19.0': + resolution: {integrity: sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==} + + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@typechain/ethers-v6@0.5.1': + resolution: {integrity: sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==} + peerDependencies: + ethers: 6.x + typechain: ^8.3.2 + typescript: '>=4.7.0' + + '@typechain/hardhat@9.1.0': + resolution: {integrity: sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==} + peerDependencies: + '@typechain/ethers-v6': ^0.5.1 + ethers: ^6.1.0 + hardhat: ^2.9.9 + typechain: ^8.3.2 + + '@types/bn.js@4.11.6': + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + + '@types/bn.js@5.1.6': + resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} + + '@types/chai-as-promised@7.1.8': + resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + + '@types/chai@4.3.20': + resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} + + '@types/concat-stream@1.6.1': + resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} + + '@types/conventional-commits-parser@5.0.1': + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + + '@types/form-data@0.0.33': + resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/lru-cache@5.1.1': + resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/mocha@10.0.10': + resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} + + '@types/node@10.17.60': + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + + '@types/node@22.13.9': + resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} + + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + + '@types/node@8.10.66': + resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} + + '@types/pbkdf2@3.1.2': + resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + + '@types/secp256k1@4.0.6': + resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + abbrev@1.0.9: + resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adm-zip@0.4.16: + resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} + engines: {node: '>=0.3.0'} + + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + amazon-cognito-identity-js@6.3.12: + resolution: {integrity: sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==} + + amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + antlr4@4.13.2: + resolution: {integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==} + engines: {node: '>=16'} + + antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-back@3.1.0: + resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} + engines: {node: '>=6'} + + array-back@4.0.2: + resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} + engines: {node: '>=8'} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + + async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-x@3.0.10: + resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + bn.js@4.11.6: + resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} + + bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} + + bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + + boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + + cbor@10.0.3: + resolution: {integrity: sha512-72Jnj81xMsqepqdcSdf2+fflz/UDsThOHy5hj2MW5F5xzHL8Oa0KQ6I6V9CwVUPxg5pf+W9xp6W2KilaRXWWtw==} + engines: {node: '>=18'} + + cbor@8.1.0: + resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} + engines: {node: '>=12.19'} + + cbor@9.0.2: + resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} + engines: {node: '>=16'} + + chai-as-promised@7.1.2: + resolution: {integrity: sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==} + peerDependencies: + chai: '>= 2.1.2 < 6' + + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-table3@0.5.1: + resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} + engines: {node: '>=6'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + + command-line-args@5.2.1: + resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} + engines: {node: '>=4.0.0'} + + command-line-usage@6.1.3: + resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} + engines: {node: '>=8.0.0'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + + cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig-typescript-loader@6.1.0: + resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + + death@1.1.0: + resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + difflib@0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@1.8.1: + resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} + engines: {node: '>=0.12.0'} + hasBin: true + + esprima@2.7.3: + resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} + engines: {node: '>=0.10.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@1.9.3: + resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} + engines: {node: '>=0.10.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eth-gas-reporter@0.2.27: + resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==} + peerDependencies: + '@codechecks/client': ^0.1.0 + peerDependenciesMeta: + '@codechecks/client': + optional: true + + ethereum-bloom-filters@1.2.0: + resolution: {integrity: sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==} + + ethereum-cryptography@0.1.3: + resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + + ethereum-cryptography@1.2.0: + resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} + + ethereum-cryptography@2.2.1: + resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} + + ethereumjs-abi@0.6.8: + resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + deprecated: This library has been deprecated and usage is discouraged. + + ethereumjs-util@6.2.1: + resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + + ethereumjs-util@7.1.5: + resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} + engines: {node: '>=10.0.0'} + + ethers@5.8.0: + resolution: {integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==} + + ethers@6.13.5: + resolution: {integrity: sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==} + engines: {node: '>=14.0.0'} + + ethjs-unit@0.1.6: + resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} + engines: {node: '>=6.5.0', npm: '>=3'} + + ethjs-util@0.1.6: + resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} + engines: {node: '>=6.5.0', npm: '>=3'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + fast-base64-decode@1.0.0: + resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fast-xml-parser@4.4.1: + resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} + hasBin: true + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-replace@3.0.0: + resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} + engines: {node: '>=4.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + fmix@0.1.0: + resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + + form-data@2.5.3: + resolution: {integrity: sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==} + engines: {node: '>= 0.12'} + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + fp-ts@1.19.3: + resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-readdir-recursive@1.1.0: + resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-port@3.2.0: + resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} + engines: {node: '>=4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + ghost-testrpc@0.0.2: + resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} + hasBin: true + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@5.0.15: + resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globby@10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + hardhat-gas-reporter@1.0.10: + resolution: {integrity: sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==} + peerDependencies: + hardhat: ^2.0.2 + + hardhat-preprocessor@0.1.5: + resolution: {integrity: sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g==} + peerDependencies: + hardhat: ^2.0.5 + + hardhat@2.22.19: + resolution: {integrity: sha512-jptJR5o6MCgNbhd7eKa3mrteR+Ggq1exmE5RUL5ydQEVKcZm0sss5laa86yZ0ixIavIvF4zzS7TdGDuyopj0sQ==} + hasBin: true + peerDependencies: + ts-node: '*' + typescript: '*' + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + http-basic@8.1.3: + resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} + engines: {node: '>=6.0.0'} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-response-object@3.0.2: + resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + immer@10.0.2: + resolution: {integrity: sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==} + + immutable@4.3.7: + resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imul@1.0.1: + resolution: {integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==} + engines: {node: '>=0.10.0'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {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. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + + io-ts@1.10.4: + resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hex-prefixed@1.0.0: + resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} + engines: {node: '>=6.5.0', npm: '>=3'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stream-stringify@3.1.6: + resolution: {integrity: sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==} + engines: {node: '>=7.10.1'} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jsonschema@1.5.0: + resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==} + + keccak@3.0.4: + resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} + engines: {node: '>=10.0.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + latest-version@7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} + + levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.4.3: + resolution: {integrity: sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru_map@0.3.3: + resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + markdown-table@1.1.3: + resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micro-ftch@0.3.1: + resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mnemonist@0.38.5: + resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + + mocha@10.8.2: + resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} + engines: {node: '>= 14.0.0'} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + murmur-128@0.2.1: + resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} + + ndjson@2.0.0: + resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} + engines: {node: '>=10'} + hasBin: true + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + + node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + + node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + + 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 + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + + nofilter@3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + + nopt@3.0.6: + resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + number-to-bn@1.7.0: + resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} + engines: {node: '>=6.5.0', npm: '>=3'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + obliterator@2.0.5: + resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + + ordinal@1.0.3: + resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-cache-control@1.0.1: + resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-solidity@1.4.2: + resolution: {integrity: sha512-VVD/4XlDjSzyPWWCPW8JEleFa8JNKFYac5kNlMjVXemQyQZKfpekPMhFZSePuXB6L+RixlFvWe20iacGjFYrLw==} + engines: {node: '>=18'} + peerDependencies: + prettier: '>=2.3.0' + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + + recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + + reduce-flatten@2.0.0: + resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} + engines: {node: '>=6'} + + registry-auth-token@5.1.0: + resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + req-cwd@2.0.0: + resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} + engines: {node: '>=4'} + + req-from@2.0.0: + resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} + engines: {node: '>=4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.1.7: + resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} + + resolve@1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + rlp@2.2.7: + resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sc-istanbul@0.4.6: + resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} + hasBin: true + + scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + + secp256k1@4.0.4: + resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} + engines: {node: '>=18.0.0'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + sha1@1.1.1: + resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + solc@0.8.26: + resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} + engines: {node: '>=10.0.0'} + hasBin: true + + solhint-plugin-prettier@0.1.0: + resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-solidity: ^1.0.0 + + solhint@5.0.5: + resolution: {integrity: sha512-WrnG6T+/UduuzSWsSOAbfq1ywLUDwNea3Gd5hg6PS+pLUm8lz2ECNr0beX609clBxmDeZ3676AiA9nPDljmbJQ==} + hasBin: true + + solidity-ast@0.4.59: + resolution: {integrity: sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g==} + + solidity-coverage@0.8.14: + resolution: {integrity: sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA==} + hasBin: true + peerDependencies: + hardhat: ^2.11.0 + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.2.0: + resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} + engines: {node: '>=0.8.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stacktrace-parser@0.1.11: + resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} + engines: {node: '>=6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-format@2.0.0: + resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} + + string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-hex-prefix@1.0.0: + resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} + engines: {node: '>=6.5.0', npm: '>=3'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + sync-request@6.1.0: + resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} + engines: {node: '>=8.0.0'} + + sync-rpc@1.3.6: + resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} + + table-layout@1.0.2: + resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} + engines: {node: '>=8.0.0'} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + then-request@6.0.2: + resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} + engines: {node: '>=6.0.0'} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-command-line-args@2.5.1: + resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} + hasBin: true + + ts-essentials@7.0.3: + resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} + peerDependencies: + typescript: '>=3.7.0' + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + 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 + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsort@0.0.1: + resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} + + tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + + type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + typechain@8.3.2: + resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} + hasBin: true + peerDependencies: + typescript: '>=4.3.0' + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + + typical@4.0.0: + resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} + engines: {node: '>=8'} + + typical@5.2.0: + resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} + engines: {node: '>=8'} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@5.28.5: + resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==} + engines: {node: '>=14.0'} + + undici@6.21.1: + resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} + engines: {node: '>=18.17'} + + unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + web3-utils@1.10.4: + resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} + engines: {node: '>=8.0.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wordwrapjs@4.0.1: + resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} + engines: {node: '>=8.0.0'} + + workerpool@6.5.1: + resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + 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 + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + 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 + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + 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 + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.2.0: + resolution: {integrity: sha512-KHBC7z61OJeaMGnF3wqNZj+GGNXOyypZviiKpQeiHirG5Ib1ImwcLBH70rbMSkKfSmUNBsdf2PwaEJtKvgmkNw==} + engines: {node: '>=12.20'} + +snapshots: + + '@adraffy/ens-normalize@1.10.1': {} + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.734.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-locate-window': 3.723.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@1.2.2': + dependencies: + '@aws-crypto/util': 1.2.2 + '@aws-sdk/types': 3.734.0 + tslib: 1.14.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.734.0 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@1.2.2': + dependencies: + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-lambda@3.758.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.758.0 + '@aws-sdk/credential-provider-node': 3.758.0 + '@aws-sdk/middleware-host-header': 3.734.0 + '@aws-sdk/middleware-logger': 3.734.0 + '@aws-sdk/middleware-recursion-detection': 3.734.0 + '@aws-sdk/middleware-user-agent': 3.758.0 + '@aws-sdk/region-config-resolver': 3.734.0 + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-endpoints': 3.743.0 + '@aws-sdk/util-user-agent-browser': 3.734.0 + '@aws-sdk/util-user-agent-node': 3.758.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.5 + '@smithy/eventstream-serde-browser': 4.0.1 + '@smithy/eventstream-serde-config-resolver': 4.0.1 + '@smithy/eventstream-serde-node': 4.0.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.6 + '@smithy/middleware-retry': 4.0.7 + '@smithy/middleware-serde': 4.0.2 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.3 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.7 + '@smithy/util-defaults-mode-node': 4.0.7 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-stream': 4.1.2 + '@smithy/util-utf8': 4.0.0 + '@smithy/util-waiter': 4.0.2 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.758.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.758.0 + '@aws-sdk/middleware-host-header': 3.734.0 + '@aws-sdk/middleware-logger': 3.734.0 + '@aws-sdk/middleware-recursion-detection': 3.734.0 + '@aws-sdk/middleware-user-agent': 3.758.0 + '@aws-sdk/region-config-resolver': 3.734.0 + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-endpoints': 3.743.0 + '@aws-sdk/util-user-agent-browser': 3.734.0 + '@aws-sdk/util-user-agent-node': 3.758.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.5 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.6 + '@smithy/middleware-retry': 4.0.7 + '@smithy/middleware-serde': 4.0.2 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.3 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.7 + '@smithy/util-defaults-mode-node': 4.0.7 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.758.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/core': 3.1.5 + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/signature-v4': 5.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/util-middleware': 4.0.1 + fast-xml-parser: 4.4.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/node-http-handler': 4.0.3 + '@smithy/property-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/util-stream': 4.1.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/credential-provider-env': 3.758.0 + '@aws-sdk/credential-provider-http': 3.758.0 + '@aws-sdk/credential-provider-process': 3.758.0 + '@aws-sdk/credential-provider-sso': 3.758.0 + '@aws-sdk/credential-provider-web-identity': 3.758.0 + '@aws-sdk/nested-clients': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.758.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.758.0 + '@aws-sdk/credential-provider-http': 3.758.0 + '@aws-sdk/credential-provider-ini': 3.758.0 + '@aws-sdk/credential-provider-process': 3.758.0 + '@aws-sdk/credential-provider-sso': 3.758.0 + '@aws-sdk/credential-provider-web-identity': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.758.0': + dependencies: + '@aws-sdk/client-sso': 3.758.0 + '@aws-sdk/core': 3.758.0 + '@aws-sdk/token-providers': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/nested-clients': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-host-header@3.734.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.734.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.734.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.758.0': + dependencies: + '@aws-sdk/core': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-endpoints': 3.743.0 + '@smithy/core': 3.1.5 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.758.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.758.0 + '@aws-sdk/middleware-host-header': 3.734.0 + '@aws-sdk/middleware-logger': 3.734.0 + '@aws-sdk/middleware-recursion-detection': 3.734.0 + '@aws-sdk/middleware-user-agent': 3.758.0 + '@aws-sdk/region-config-resolver': 3.734.0 + '@aws-sdk/types': 3.734.0 + '@aws-sdk/util-endpoints': 3.743.0 + '@aws-sdk/util-user-agent-browser': 3.734.0 + '@aws-sdk/util-user-agent-node': 3.758.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.5 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.6 + '@smithy/middleware-retry': 4.0.7 + '@smithy/middleware-serde': 4.0.2 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.3 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.7 + '@smithy/util-defaults-mode-node': 4.0.7 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.734.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.1 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.758.0': + dependencies: + '@aws-sdk/nested-clients': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.734.0': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.743.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/types': 4.1.0 + '@smithy/util-endpoints': 3.0.1 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.723.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.734.0': + dependencies: + '@aws-sdk/types': 3.734.0 + '@smithy/types': 4.1.0 + bowser: 2.11.0 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.758.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.758.0 + '@aws-sdk/types': 3.734.0 + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.8.1 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.25.9': {} + + '@bytecodealliance/preview2-shim@0.17.0': {} + + '@commitlint/cli@19.7.1(@types/node@22.13.9)(typescript@5.8.2)': + dependencies: + '@commitlint/format': 19.5.0 + '@commitlint/lint': 19.7.1 + '@commitlint/load': 19.6.1(@types/node@22.13.9)(typescript@5.8.2) + '@commitlint/read': 19.5.0 + '@commitlint/types': 19.5.0 + tinyexec: 0.3.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.7.1': + dependencies: + '@commitlint/types': 19.5.0 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.5.0': + dependencies: + '@commitlint/types': 19.5.0 + ajv: 8.17.1 + + '@commitlint/ensure@19.5.0': + dependencies: + '@commitlint/types': 19.5.0 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@19.5.0': {} + + '@commitlint/format@19.5.0': + dependencies: + '@commitlint/types': 19.5.0 + chalk: 5.4.1 + + '@commitlint/is-ignored@19.7.1': + dependencies: + '@commitlint/types': 19.5.0 + semver: 7.7.1 + + '@commitlint/lint@19.7.1': + dependencies: + '@commitlint/is-ignored': 19.7.1 + '@commitlint/parse': 19.5.0 + '@commitlint/rules': 19.6.0 + '@commitlint/types': 19.5.0 + + '@commitlint/load@19.6.1(@types/node@22.13.9)(typescript@5.8.2)': + dependencies: + '@commitlint/config-validator': 19.5.0 + '@commitlint/execute-rule': 19.5.0 + '@commitlint/resolve-extends': 19.5.0 + '@commitlint/types': 19.5.0 + chalk: 5.4.1 + cosmiconfig: 9.0.0(typescript@5.8.2) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.9)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@19.5.0': {} + + '@commitlint/parse@19.5.0': + dependencies: + '@commitlint/types': 19.5.0 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.5.0': + dependencies: + '@commitlint/top-level': 19.5.0 + '@commitlint/types': 19.5.0 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 0.3.2 + + '@commitlint/resolve-extends@19.5.0': + dependencies: + '@commitlint/config-validator': 19.5.0 + '@commitlint/types': 19.5.0 + global-directory: 4.0.1 + import-meta-resolve: 4.1.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@19.6.0': + dependencies: + '@commitlint/ensure': 19.5.0 + '@commitlint/message': 19.5.0 + '@commitlint/to-lines': 19.5.0 + '@commitlint/types': 19.5.0 + + '@commitlint/to-lines@19.5.0': {} + + '@commitlint/top-level@19.5.0': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.5.0': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.4.1 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@ethereumjs/rlp@4.0.1': {} + + '@ethereumjs/util@8.1.0': + dependencies: + '@ethereumjs/rlp': 4.0.1 + ethereum-cryptography: 2.2.1 + micro-ftch: 0.3.1 + + '@ethersproject/abi@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/abstract-provider@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + + '@ethersproject/abstract-signer@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/address@5.6.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/rlp': 5.8.0 + + '@ethersproject/address@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/rlp': 5.8.0 + + '@ethersproject/base64@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + + '@ethersproject/basex@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/bignumber@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + bn.js: 5.2.1 + + '@ethersproject/bytes@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/constants@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + + '@ethersproject/contracts@5.8.0': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + + '@ethersproject/hash@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/hdnode@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/json-wallets@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + + '@ethersproject/keccak256@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + js-sha3: 0.8.0 + + '@ethersproject/logger@5.8.0': {} + + '@ethersproject/networks@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/pbkdf2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/sha2': 5.8.0 + + '@ethersproject/properties@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/providers@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + bech32: 1.1.4 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ethersproject/random@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/rlp@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/sha2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + hash.js: 1.1.7 + + '@ethersproject/signing-key@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + bn.js: 5.2.1 + elliptic: 6.6.1 + hash.js: 1.1.7 + + '@ethersproject/solidity@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/strings@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/transactions@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + + '@ethersproject/units@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/wallet@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/web@5.8.0': + dependencies: + '@ethersproject/base64': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/wordlists@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@fastify/busboy@2.1.1': {} + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@metamask/eth-sig-util@4.0.1': + 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 + + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + + '@noble/curves@1.4.2': + dependencies: + '@noble/hashes': 1.4.0 + + '@noble/hashes@1.2.0': {} + + '@noble/hashes@1.3.2': {} + + '@noble/hashes@1.4.0': {} + + '@noble/hashes@1.7.1': {} + + '@noble/secp256k1@1.7.1': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@nomicfoundation/edr-darwin-arm64@0.8.0': {} + + '@nomicfoundation/edr-darwin-x64@0.8.0': {} + + '@nomicfoundation/edr-linux-arm64-gnu@0.8.0': {} + + '@nomicfoundation/edr-linux-arm64-musl@0.8.0': {} + + '@nomicfoundation/edr-linux-x64-gnu@0.8.0': {} + + '@nomicfoundation/edr-linux-x64-musl@0.8.0': {} + + '@nomicfoundation/edr-win32-x64-msvc@0.8.0': {} + + '@nomicfoundation/edr@0.8.0': + dependencies: + '@nomicfoundation/edr-darwin-arm64': 0.8.0 + '@nomicfoundation/edr-darwin-x64': 0.8.0 + '@nomicfoundation/edr-linux-arm64-gnu': 0.8.0 + '@nomicfoundation/edr-linux-arm64-musl': 0.8.0 + '@nomicfoundation/edr-linux-x64-gnu': 0.8.0 + '@nomicfoundation/edr-linux-x64-musl': 0.8.0 + '@nomicfoundation/edr-win32-x64-msvc': 0.8.0 + + '@nomicfoundation/ethereumjs-common@4.0.4': + dependencies: + '@nomicfoundation/ethereumjs-util': 9.0.4 + transitivePeerDependencies: + - c-kzg + + '@nomicfoundation/ethereumjs-rlp@5.0.4': {} + + '@nomicfoundation/ethereumjs-tx@5.0.4': + dependencies: + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + ethereum-cryptography: 0.1.3 + + '@nomicfoundation/ethereumjs-util@9.0.4': + dependencies: + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + ethereum-cryptography: 0.1.3 + + '@nomicfoundation/hardhat-chai-matchers@2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(chai@4.5.0)(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@types/chai-as-promised': 7.1.8 + chai: 4.5.0 + chai-as-promised: 7.1.2(chai@4.5.0) + deep-eql: 4.1.4 + ethers: 6.13.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + ordinal: 1.0.3 + + '@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + debug: 4.4.0(supports-color@8.1.1) + ethers: 6.13.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + lodash.isequal: 4.5.0 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/hardhat-foundry@1.1.3(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + picocolors: 1.1.1 + + '@nomicfoundation/hardhat-ignition-ethers@0.15.10(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/hardhat-ignition@0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/ignition-core@0.15.10)(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-ignition': 0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/ignition-core': 0.15.10 + ethers: 6.13.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + + '@nomicfoundation/hardhat-ignition@0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/ignition-core': 0.15.10 + '@nomicfoundation/ignition-ui': 0.15.10 + chalk: 4.1.2 + debug: 4.4.0(supports-color@8.1.1) + fs-extra: 10.1.0 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + json5: 2.2.3 + prompts: 2.4.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + ethereumjs-util: 7.1.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + + '@nomicfoundation/hardhat-toolbox@5.0.0(0e7772daf0a8bbd3d2fcd6fbe17c525b)': + dependencies: + '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(chai@4.5.0)(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-ignition-ethers': 0.15.10(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/hardhat-ignition@0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/ignition-core@0.15.10)(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@typechain/ethers-v6': 0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2))(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))(typechain@8.3.2(typescript@5.8.2)) + '@types/chai': 4.3.20 + '@types/mocha': 10.0.10 + '@types/node': 22.13.9 + chai: 4.5.0 + ethers: 6.13.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + hardhat-gas-reporter: 1.0.10(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + solidity-coverage: 0.8.14(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + ts-node: 10.9.2(@types/node@22.13.9)(typescript@5.8.2) + typechain: 8.3.2(typescript@5.8.2) + typescript: 5.8.2 + + '@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/address': 5.8.0 + cbor: 8.1.0 + debug: 4.4.0(supports-color@8.1.1) + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + lodash.clonedeep: 4.5.0 + picocolors: 1.1.1 + semver: 6.3.1 + table: 6.9.0 + undici: 5.28.5 + transitivePeerDependencies: + - supports-color + + '@nomicfoundation/ignition-core@0.15.10': + dependencies: + '@ethersproject/address': 5.6.1 + '@nomicfoundation/solidity-analyzer': 0.1.2 + cbor: 9.0.2 + debug: 4.4.0(supports-color@8.1.1) + ethers: 6.13.5 + fs-extra: 10.1.0 + immer: 10.0.2 + lodash: 4.17.21 + ndjson: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@nomicfoundation/ignition-ui@0.15.10': {} + + '@nomicfoundation/slang@0.18.3': + dependencies: + '@bytecodealliance/preview2-shim': 0.17.0 + + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2': + optional: true + + '@nomicfoundation/solidity-analyzer@0.1.2': + optionalDependencies: + '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.2 + '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.2 + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu': 0.1.2 + '@nomicfoundation/solidity-analyzer-linux-arm64-musl': 0.1.2 + '@nomicfoundation/solidity-analyzer-linux-x64-gnu': 0.1.2 + '@nomicfoundation/solidity-analyzer-linux-x64-musl': 0.1.2 + '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.2 + + '@nomiclabs/hardhat-solhint@4.0.1(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))(typescript@5.8.2)': + dependencies: + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + solhint: 5.0.5(typescript@5.8.2) + transitivePeerDependencies: + - typescript + + '@openzeppelin/defender-sdk-base-client@2.4.0': + dependencies: + '@aws-sdk/client-lambda': 3.758.0 + amazon-cognito-identity-js: 6.3.12 + async-retry: 1.3.3 + transitivePeerDependencies: + - aws-crt + - encoding + + '@openzeppelin/defender-sdk-deploy-client@2.4.0(debug@4.4.0)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 2.4.0 + axios: 1.8.2(debug@4.4.0) + lodash: 4.17.21 + transitivePeerDependencies: + - aws-crt + - debug + - encoding + + '@openzeppelin/defender-sdk-network-client@2.4.0(debug@4.4.0)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 2.4.0 + axios: 1.8.2(debug@4.4.0) + lodash: 4.17.21 + transitivePeerDependencies: + - aws-crt + - debug + - encoding + + '@openzeppelin/hardhat-upgrades@3.9.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)))(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))': + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + '@openzeppelin/defender-sdk-base-client': 2.4.0 + '@openzeppelin/defender-sdk-deploy-client': 2.4.0(debug@4.4.0) + '@openzeppelin/defender-sdk-network-client': 2.4.0(debug@4.4.0) + '@openzeppelin/upgrades-core': 1.42.1 + chalk: 4.1.2 + debug: 4.4.0(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + ethers: 6.13.5 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + proper-lockfile: 4.1.2 + undici: 6.21.1 + optionalDependencies: + '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)) + transitivePeerDependencies: + - aws-crt + - encoding + - supports-color + + '@openzeppelin/upgrades-core@1.42.1': + dependencies: + '@nomicfoundation/slang': 0.18.3 + cbor: 10.0.3 + chalk: 4.1.2 + compare-versions: 6.1.1 + debug: 4.4.0(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + minimatch: 9.0.5 + minimist: 1.2.8 + proper-lockfile: 4.1.2 + solidity-ast: 0.4.59 + transitivePeerDependencies: + - supports-color + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@2.3.1': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@prettier/sync@0.3.0(prettier@3.5.3)': + dependencies: + prettier: 3.5.3 + + '@scure/base@1.1.9': {} + + '@scure/bip32@1.1.5': + dependencies: + '@noble/hashes': 1.2.0 + '@noble/secp256k1': 1.7.1 + '@scure/base': 1.1.9 + + '@scure/bip32@1.4.0': + dependencies: + '@noble/curves': 1.4.2 + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.9 + + '@scure/bip39@1.1.1': + dependencies: + '@noble/hashes': 1.2.0 + '@scure/base': 1.1.9 + + '@scure/bip39@1.3.0': + dependencies: + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.9 + + '@sentry/core@5.30.0': + 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 + + '@sentry/hub@5.30.0': + dependencies: + '@sentry/types': 5.30.0 + '@sentry/utils': 5.30.0 + tslib: 1.14.1 + + '@sentry/minimal@5.30.0': + dependencies: + '@sentry/hub': 5.30.0 + '@sentry/types': 5.30.0 + tslib: 1.14.1 + + '@sentry/node@5.30.0': + 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 + + '@sentry/tracing@5.30.0': + 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 + + '@sentry/types@5.30.0': {} + + '@sentry/utils@5.30.0': + dependencies: + '@sentry/types': 5.30.0 + tslib: 1.14.1 + + '@sindresorhus/is@5.6.0': {} + + '@smithy/abort-controller@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/config-resolver@4.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.1 + tslib: 2.8.1 + + '@smithy/core@3.1.5': + dependencies: + '@smithy/middleware-serde': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-stream': 4.1.2 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.0.1': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.1.0 + '@smithy/util-hex-encoding': 4.0.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.0.1': + dependencies: + '@smithy/eventstream-serde-universal': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.0.1': + dependencies: + '@smithy/eventstream-serde-universal': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.0.1': + dependencies: + '@smithy/eventstream-codec': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.0.1': + dependencies: + '@smithy/protocol-http': 5.0.1 + '@smithy/querystring-builder': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-base64': 4.0.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.0.1': + dependencies: + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.0.6': + dependencies: + '@smithy/core': 3.1.5 + '@smithy/middleware-serde': 4.0.2 + '@smithy/node-config-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-middleware': 4.0.1 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.0.7': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/service-error-classification': 4.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + tslib: 2.8.1 + uuid: 9.0.1 + + '@smithy/middleware-serde@4.0.2': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.0.1': + dependencies: + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.0.3': + dependencies: + '@smithy/abort-controller': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/querystring-builder': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + '@smithy/util-uri-escape': 4.0.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + + '@smithy/shared-ini-file-loader@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.0.1': + dependencies: + '@smithy/is-array-buffer': 4.0.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-hex-encoding': 4.0.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-uri-escape': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.1.6': + dependencies: + '@smithy/core': 3.1.5 + '@smithy/middleware-endpoint': 4.0.6 + '@smithy/middleware-stack': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-stream': 4.1.2 + tslib: 2.8.1 + + '@smithy/types@4.1.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.0.1': + dependencies: + '@smithy/querystring-parser': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.0.0': + dependencies: + '@smithy/is-array-buffer': 4.0.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.0.7': + dependencies: + '@smithy/property-provider': 4.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + bowser: 2.11.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.0.7': + dependencies: + '@smithy/config-resolver': 4.0.1 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/smithy-client': 4.1.6 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.0.1': + dependencies: + '@smithy/service-error-classification': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.1.2': + dependencies: + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/node-http-handler': 4.0.3 + '@smithy/types': 4.1.0 + '@smithy/util-base64': 4.0.0 + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-hex-encoding': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + tslib: 2.8.1 + + '@smithy/util-waiter@4.0.2': + dependencies: + '@smithy/abort-controller': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.8.1 + + '@solidity-parser/parser@0.14.5': + dependencies: + antlr4ts: 0.5.0-alpha.4 + + '@solidity-parser/parser@0.19.0': {} + + '@szmarczak/http-timer@5.0.1': + dependencies: + defer-to-connect: 2.0.1 + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@typechain/ethers-v6@0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2)': + dependencies: + ethers: 6.13.5 + lodash: 4.17.21 + ts-essentials: 7.0.3(typescript@5.8.2) + typechain: 8.3.2(typescript@5.8.2) + typescript: 5.8.2 + + '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2))(ethers@6.13.5)(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2))(typechain@8.3.2(typescript@5.8.2))': + dependencies: + '@typechain/ethers-v6': 0.5.1(ethers@6.13.5)(typechain@8.3.2(typescript@5.8.2))(typescript@5.8.2) + ethers: 6.13.5 + fs-extra: 9.1.0 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + typechain: 8.3.2(typescript@5.8.2) + + '@types/bn.js@4.11.6': + dependencies: + '@types/node': 22.13.9 + + '@types/bn.js@5.1.6': + dependencies: + '@types/node': 22.13.9 + + '@types/chai-as-promised@7.1.8': + dependencies: + '@types/chai': 4.3.20 + + '@types/chai@4.3.20': {} + + '@types/concat-stream@1.6.1': + dependencies: + '@types/node': 22.13.9 + + '@types/conventional-commits-parser@5.0.1': + dependencies: + '@types/node': 22.13.9 + + '@types/form-data@0.0.33': + dependencies: + '@types/node': 22.13.9 + + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.13.9 + + '@types/http-cache-semantics@4.0.4': {} + + '@types/lru-cache@5.1.1': {} + + '@types/minimatch@5.1.2': {} + + '@types/mocha@10.0.10': {} + + '@types/node@10.17.60': {} + + '@types/node@22.13.9': + dependencies: + undici-types: 6.20.0 + + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + + '@types/node@8.10.66': {} + + '@types/pbkdf2@3.1.2': + dependencies: + '@types/node': 22.13.9 + + '@types/prettier@2.7.3': {} + + '@types/qs@6.9.18': {} + + '@types/secp256k1@4.0.6': + dependencies: + '@types/node': 22.13.9 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + abbrev@1.0.9: {} + + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + adm-zip@0.4.16: {} + + aes-js@3.0.0: {} + + aes-js@4.0.0-beta.5: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv@6.12.6: + 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 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + amazon-cognito-identity-js@6.3.12: + 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 + + amdefine@1.0.1: + optional: true + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + + ansi-regex@3.0.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + antlr4@4.13.2: {} + + antlr4ts@0.5.0-alpha.4: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-back@3.1.0: {} + + array-back@4.0.2: {} + + array-ify@1.0.0: {} + + array-union@2.1.0: {} + + array-uniq@1.0.3: {} + + asap@2.0.6: {} + + assertion-error@1.1.0: {} + + ast-parents@0.0.1: {} + + astral-regex@2.0.0: {} + + async-retry@1.3.3: + dependencies: + retry: 0.13.1 + + async@1.5.2: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + axios@1.8.2(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + base-x@3.0.10: + dependencies: + safe-buffer: 5.2.1 + + base64-js@1.5.1: {} + + bech32@1.1.4: {} + + binary-extensions@2.3.0: {} + + blakejs@1.2.1: {} + + bn.js@4.11.6: {} + + bn.js@4.12.1: {} + + bn.js@5.2.1: {} + + bowser@2.11.0: {} + + boxen@5.1.2: + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brorand@1.1.0: {} + + browser-stdout@1.3.1: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.6 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + bs58@4.0.1: + dependencies: + base-x: 3.0.10 + + bs58check@2.1.2: + dependencies: + bs58: 4.0.1 + create-hash: 1.2.0 + safe-buffer: 5.2.1 + + buffer-from@1.1.2: {} + + buffer-xor@1.0.3: {} + + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + + bytes@3.1.2: {} + + cacheable-lookup@7.0.0: {} + + cacheable-request@10.2.14: + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.1 + responselike: 3.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caseless@0.12.0: {} + + cbor@10.0.3: + dependencies: + nofilter: 3.1.0 + + cbor@8.1.0: + dependencies: + nofilter: 3.1.0 + + cbor@9.0.2: + dependencies: + nofilter: 3.1.0 + + chai-as-promised@7.1.2(chai@4.5.0): + dependencies: + chai: 4.5.0 + check-error: 1.0.3 + + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.4.1: {} + + charenc@0.0.2: {} + + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + 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 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + ci-info@2.0.0: {} + + cipher-base@1.0.6: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + clean-stack@2.2.0: {} + + cli-boxes@2.2.1: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-table3@0.5.1: + dependencies: + object-assign: 4.1.1 + string-width: 2.1.1 + optionalDependencies: + colors: 1.4.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + colors@1.4.0: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + command-exists@1.2.9: {} + + command-line-args@5.2.1: + dependencies: + array-back: 3.1.0 + find-replace: 3.0.0 + lodash.camelcase: 4.3.0 + typical: 4.0.0 + + command-line-usage@6.1.3: + dependencies: + array-back: 4.0.2 + chalk: 2.4.2 + table-layout: 1.0.2 + typical: 5.2.0 + + commander@10.0.1: {} + + commander@13.1.0: {} + + commander@8.3.0: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + compare-versions@6.1.1: {} + + concat-map@0.0.1: {} + + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + cookie@0.4.2: {} + + core-util-is@1.0.3: {} + + cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.9)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2): + dependencies: + '@types/node': 22.13.9 + cosmiconfig: 9.0.0(typescript@5.8.2) + jiti: 2.4.2 + typescript: 5.8.2 + + cosmiconfig@8.3.6(typescript@5.8.2): + dependencies: + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.8.2 + + cosmiconfig@9.0.0(typescript@5.8.2): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.8.2 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.6 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + create-require@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypt@0.0.2: {} + + dargs@8.1.0: {} + + death@1.1.0: {} + + debug@4.4.0(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize@4.0.0: {} + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-eql@4.1.4: + dependencies: + type-detect: 4.1.0 + + deep-extend@0.6.0: {} + + deep-is@0.1.4: {} + + defer-to-connect@2.0.1: {} + + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + diff@4.0.2: {} + + diff@5.2.0: {} + + difflib@0.2.4: + dependencies: + heap: 0.2.7 + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + dotenv@16.4.7: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.1 + 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 + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + encode-utf8@1.0.3: {} + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + env-paths@2.2.1: {} + + environment@1.1.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escodegen@1.8.1: + dependencies: + esprima: 2.7.3 + estraverse: 1.9.3 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.2.0 + + esprima@2.7.3: {} + + esprima@4.0.1: {} + + estraverse@1.9.3: {} + + esutils@2.0.3: {} + + eth-gas-reporter@0.2.27: + dependencies: + '@solidity-parser/parser': 0.14.5 + axios: 1.8.2(debug@4.4.0) + cli-table3: 0.5.1 + colors: 1.4.0 + ethereum-cryptography: 1.2.0 + ethers: 5.8.0 + fs-readdir-recursive: 1.1.0 + lodash: 4.17.21 + markdown-table: 1.1.3 + mocha: 10.8.2 + req-cwd: 2.0.0 + sha1: 1.1.1 + sync-request: 6.1.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + ethereum-bloom-filters@1.2.0: + dependencies: + '@noble/hashes': 1.7.1 + + ethereum-cryptography@0.1.3: + dependencies: + '@types/pbkdf2': 3.1.2 + '@types/secp256k1': 4.0.6 + 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.4 + pbkdf2: 3.1.2 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + scrypt-js: 3.0.1 + secp256k1: 4.0.4 + setimmediate: 1.0.5 + + ethereum-cryptography@1.2.0: + dependencies: + '@noble/hashes': 1.2.0 + '@noble/secp256k1': 1.7.1 + '@scure/bip32': 1.1.5 + '@scure/bip39': 1.1.1 + + ethereum-cryptography@2.2.1: + dependencies: + '@noble/curves': 1.4.2 + '@noble/hashes': 1.4.0 + '@scure/bip32': 1.4.0 + '@scure/bip39': 1.3.0 + + ethereumjs-abi@0.6.8: + dependencies: + bn.js: 4.12.1 + ethereumjs-util: 6.2.1 + + ethereumjs-util@6.2.1: + dependencies: + '@types/bn.js': 4.11.6 + bn.js: 4.12.1 + create-hash: 1.2.0 + elliptic: 6.6.1 + ethereum-cryptography: 0.1.3 + ethjs-util: 0.1.6 + rlp: 2.2.7 + + ethereumjs-util@7.1.5: + dependencies: + '@types/bn.js': 5.1.6 + bn.js: 5.2.1 + create-hash: 1.2.0 + ethereum-cryptography: 0.1.3 + rlp: 2.2.7 + + ethers@5.8.0: + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/contracts': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/providers': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/solidity': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/units': 5.8.0 + '@ethersproject/wallet': 5.8.0 + '@ethersproject/web': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + ethers@6.13.5: + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + ethjs-unit@0.1.6: + dependencies: + bn.js: 4.11.6 + number-to-bn: 1.7.0 + + ethjs-util@0.1.6: + dependencies: + is-hex-prefixed: 1.0.0 + strip-hex-prefix: 1.0.0 + + eventemitter3@5.0.1: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + fast-base64-decode@1.0.0: {} + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.3: + 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.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.6: {} + + fast-xml-parser@4.4.1: + dependencies: + strnum: 1.1.2 + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-replace@3.0.0: + dependencies: + array-back: 3.1.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + flat@5.0.2: {} + + fmix@0.1.0: + dependencies: + imul: 1.0.1 + + follow-redirects@1.15.9(debug@4.4.0): + optionalDependencies: + debug: 4.4.0(supports-color@8.1.1) + + form-data-encoder@2.1.4: {} + + form-data@2.5.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + safe-buffer: 5.2.1 + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + fp-ts@1.19.3: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-readdir-recursive@1.1.0: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-port@3.2.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + ghost-testrpc@0.0.2: + dependencies: + chalk: 2.4.2 + node-emoji: 1.11.0 + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@5.0.15: + dependencies: + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@7.1.7: + 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 + + glob@7.2.3: + 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 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + globby@10.0.2: + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + glob: 7.2.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + got@12.6.1: + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + + graceful-fs@4.2.10: {} + + graceful-fs@4.2.11: {} + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + hardhat-gas-reporter@1.0.10(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)): + dependencies: + array-uniq: 1.0.3 + eth-gas-reporter: 0.2.27 + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + sha1: 1.1.1 + transitivePeerDependencies: + - '@codechecks/client' + - bufferutil + - debug + - utf-8-validate + + hardhat-preprocessor@0.1.5(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)): + dependencies: + hardhat: 2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + murmur-128: 0.2.1 + + hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2): + dependencies: + '@ethersproject/abi': 5.8.0 + '@metamask/eth-sig-util': 4.0.1 + '@nomicfoundation/edr': 0.8.0 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + '@nomicfoundation/solidity-analyzer': 0.1.2 + '@sentry/node': 5.30.0 + '@types/bn.js': 5.1.6 + '@types/lru-cache': 5.1.1 + adm-zip: 0.4.16 + aggregate-error: 3.1.0 + ansi-escapes: 4.3.2 + boxen: 5.1.2 + chokidar: 4.0.3 + ci-info: 2.0.0 + debug: 4.4.0(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: 5.0.0 + fp-ts: 1.19.3 + fs-extra: 7.0.1 + immutable: 4.3.7 + io-ts: 1.10.4 + json-stream-stringify: 3.1.6 + keccak: 3.0.4 + lodash: 4.17.21 + mnemonist: 0.38.5 + mocha: 10.8.2 + p-map: 4.0.0 + picocolors: 1.1.1 + raw-body: 2.5.2 + resolve: 1.17.0 + semver: 6.3.1 + solc: 0.8.26(debug@4.4.0) + source-map-support: 0.5.21 + stacktrace-parser: 0.1.11 + tinyglobby: 0.2.12 + tsort: 0.0.1 + undici: 5.28.5 + uuid: 8.3.2 + ws: 7.5.10 + optionalDependencies: + ts-node: 10.9.2(@types/node@22.13.9)(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - bufferutil + - c-kzg + - supports-color + - utf-8-validate + + has-flag@1.0.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + heap@0.2.7: {} + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + http-basic@8.1.3: + dependencies: + caseless: 0.12.0 + concat-stream: 1.6.2 + http-response-object: 3.0.2 + parse-cache-control: 1.0.1 + + http-cache-semantics@4.1.1: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-response-object@3.0.2: + dependencies: + '@types/node': 10.17.60 + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + human-signals@5.0.0: {} + + husky@9.1.7: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + immer@10.0.2: {} + + immutable@4.3.7: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.1.0: {} + + imul@1.0.1: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + + interpret@1.4.0: {} + + io-ts@1.10.4: + dependencies: + fp-ts: 1.19.3 + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@2.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hex-prefixed@1.0.0: {} + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-plain-obj@2.1.0: {} + + is-stream@3.0.0: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-unicode-supported@0.1.0: {} + + isarray@1.0.0: {} + + isexe@2.0.0: {} + + isomorphic-unfetch@3.1.0: + dependencies: + node-fetch: 2.7.0 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + + jiti@2.4.2: {} + + js-cookie@2.2.1: {} + + js-sha3@0.8.0: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stream-stringify@3.1.6: {} + + json-stringify-safe@5.0.1: {} + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + jsonschema@1.5.0: {} + + keccak@3.0.4: + dependencies: + node-addon-api: 2.0.2 + node-gyp-build: 4.8.4 + readable-stream: 3.6.2 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + latest-version@7.0.0: + dependencies: + package-json: 8.1.1 + + levn@0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.4.3: + dependencies: + chalk: 5.4.1 + commander: 13.1.0 + debug: 4.4.0(supports-color@8.1.1) + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.2.5 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.7.0 + transitivePeerDependencies: + - supports-color + + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.isequal@4.5.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.truncate@4.4.2: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + lowercase-keys@3.0.0: {} + + lru_map@0.3.3: {} + + make-error@1.3.6: {} + + markdown-table@1.1.3: {} + + math-intrinsics@1.1.0: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + memorystream@0.3.1: {} + + meow@12.1.1: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micro-ftch@0.3.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + mimic-response@3.1.0: {} + + mimic-response@4.0.0: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: {} + + mnemonist@0.38.5: + dependencies: + obliterator: 2.0.5 + + mocha@10.8.2: + dependencies: + ansi-colors: 4.1.3 + browser-stdout: 1.3.1 + chokidar: 3.6.0 + debug: 4.4.0(supports-color@8.1.1) + diff: 5.2.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 8.1.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.1.6 + ms: 2.1.3 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.5.1 + yargs: 16.2.0 + yargs-parser: 20.2.9 + yargs-unparser: 2.0.0 + + ms@2.1.3: {} + + murmur-128@0.2.1: + dependencies: + encode-utf8: 1.0.3 + fmix: 0.1.0 + imul: 1.0.1 + + ndjson@2.0.0: + dependencies: + json-stringify-safe: 5.0.1 + minimist: 1.2.8 + readable-stream: 3.6.2 + split2: 3.2.2 + through2: 4.0.2 + + neo-async@2.6.2: {} + + node-addon-api@2.0.2: {} + + node-addon-api@5.1.0: {} + + node-emoji@1.11.0: + dependencies: + lodash: 4.17.21 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build@4.8.4: {} + + nofilter@3.1.0: {} + + nopt@3.0.6: + dependencies: + abbrev: 1.0.9 + + normalize-path@3.0.0: {} + + normalize-url@8.0.1: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + number-to-bn@1.7.0: + dependencies: + bn.js: 4.11.6 + strip-hex-prefix: 1.0.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + obliterator@2.0.5: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + optionator@0.8.3: + 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 + + ordinal@1.0.3: {} + + os-tmpdir@1.0.2: {} + + p-cancelable@3.0.0: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + package-json@8.1.1: + dependencies: + got: 12.6.1 + registry-auth-token: 5.1.0 + registry-url: 6.0.1 + semver: 7.7.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-cache-control@1.0.1: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-type@4.0.0: {} + + pathval@1.1.1: {} + + pbkdf2@3.1.2: + 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 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pidtree@0.6.0: {} + + pify@4.0.1: {} + + pluralize@8.0.0: {} + + prelude-ls@1.1.2: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier-plugin-solidity@1.4.2(prettier@3.5.3): + dependencies: + '@solidity-parser/parser': 0.19.0 + prettier: 3.5.3 + semver: 7.7.1 + + prettier@2.8.8: {} + + prettier@3.5.3: {} + + process-nextick-args@2.0.1: {} + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + proto-list@1.2.4: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + quick-lru@5.1.1: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + readable-stream@2.3.8: + 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 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + rechoir@0.6.2: + dependencies: + resolve: 1.17.0 + + recursive-readdir@2.2.3: + dependencies: + minimatch: 3.1.2 + + reduce-flatten@2.0.0: {} + + registry-auth-token@5.1.0: + dependencies: + '@pnpm/npm-conf': 2.3.1 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + req-cwd@2.0.0: + dependencies: + req-from: 2.0.0 + + req-from@2.0.0: + dependencies: + resolve-from: 3.0.0 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-alpn@1.2.1: {} + + resolve-from@3.0.0: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve@1.1.7: {} + + resolve@1.17.0: + dependencies: + path-parse: 1.0.7 + + responselike@3.0.0: + dependencies: + lowercase-keys: 3.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + retry@0.12.0: {} + + retry@0.13.1: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + ripemd160@2.0.2: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + + rlp@2.2.7: + dependencies: + bn.js: 5.2.1 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sc-istanbul@0.4.6: + 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 + + scrypt-js@3.0.1: {} + + secp256k1@4.0.4: + dependencies: + elliptic: 6.6.1 + node-addon-api: 5.1.0 + node-gyp-build: 4.8.4 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.7.1: {} + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sha.js@2.4.11: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + sha1@1.1.1: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shelljs@0.8.5: + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + solc@0.8.26(debug@4.4.0): + dependencies: + command-exists: 1.2.9 + commander: 8.3.0 + follow-redirects: 1.15.9(debug@4.4.0) + js-sha3: 0.8.0 + memorystream: 0.3.1 + semver: 5.7.2 + tmp: 0.0.33 + transitivePeerDependencies: + - debug + + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.4.2(prettier@3.5.3))(prettier@3.5.3): + dependencies: + '@prettier/sync': 0.3.0(prettier@3.5.3) + prettier: 3.5.3 + prettier-linter-helpers: 1.0.0 + prettier-plugin-solidity: 1.4.2(prettier@3.5.3) + + solhint@5.0.5(typescript@5.8.2): + dependencies: + '@solidity-parser/parser': 0.19.0 + ajv: 6.12.6 + antlr4: 4.13.2 + ast-parents: 0.0.1 + chalk: 4.1.2 + commander: 10.0.1 + cosmiconfig: 8.3.6(typescript@5.8.2) + fast-diff: 1.3.0 + glob: 8.1.0 + ignore: 5.3.2 + js-yaml: 4.1.0 + latest-version: 7.0.0 + lodash: 4.17.21 + pluralize: 8.0.0 + semver: 7.7.1 + strip-ansi: 6.0.1 + table: 6.9.0 + text-table: 0.2.0 + optionalDependencies: + prettier: 2.8.8 + transitivePeerDependencies: + - typescript + + solidity-ast@0.4.59: {} + + solidity-coverage@0.8.14(hardhat@2.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2)): + dependencies: + '@ethersproject/abi': 5.8.0 + '@solidity-parser/parser': 0.19.0 + chalk: 2.4.2 + death: 1.1.0 + 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.22.19(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))(typescript@5.8.2) + jsonschema: 1.5.0 + lodash: 4.17.21 + mocha: 10.8.2 + node-emoji: 1.11.0 + pify: 4.0.1 + recursive-readdir: 2.2.3 + sc-istanbul: 0.4.6 + semver: 7.7.1 + shelljs: 0.8.5 + web3-utils: 1.10.4 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.2.0: + dependencies: + amdefine: 1.0.1 + optional: true + + source-map@0.6.1: {} + + split2@3.2.2: + dependencies: + readable-stream: 3.6.2 + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + stacktrace-parser@0.1.11: + dependencies: + type-fest: 0.7.1 + + statuses@2.0.1: {} + + string-argv@0.3.2: {} + + string-format@2.0.0: {} + + string-width@2.1.1: + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@4.0.0: + dependencies: + ansi-regex: 3.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-final-newline@3.0.0: {} + + strip-hex-prefix@1.0.0: + dependencies: + is-hex-prefixed: 1.0.0 + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + strnum@1.1.2: {} + + supports-color@3.2.3: + dependencies: + has-flag: 1.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + sync-request@6.1.0: + dependencies: + http-response-object: 3.0.2 + sync-rpc: 1.3.6 + then-request: 6.0.2 + + sync-rpc@1.3.6: + dependencies: + get-port: 3.2.0 + + table-layout@1.0.2: + dependencies: + array-back: 4.0.2 + deep-extend: 0.6.0 + typical: 5.2.0 + wordwrapjs: 4.0.1 + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + text-extensions@2.4.0: {} + + text-table@0.2.0: {} + + then-request@6.0.2: + dependencies: + '@types/concat-stream': 1.6.1 + '@types/form-data': 0.0.33 + '@types/node': 8.10.66 + '@types/qs': 6.9.18 + caseless: 0.12.0 + concat-stream: 1.6.2 + form-data: 2.5.3 + http-basic: 8.1.3 + http-response-object: 3.0.2 + promise: 8.3.0 + qs: 6.14.0 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + through@2.3.8: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + tr46@0.0.3: {} + + ts-command-line-args@2.5.1: + dependencies: + chalk: 4.1.2 + command-line-args: 5.2.1 + command-line-usage: 6.1.3 + string-format: 2.0.0 + + ts-essentials@7.0.3(typescript@5.8.2): + dependencies: + typescript: 5.8.2 + + ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.13.9 + acorn: 8.14.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.8.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tslib@1.14.1: {} + + tslib@2.7.0: {} + + tslib@2.8.1: {} + + tsort@0.0.1: {} + + tweetnacl-util@0.15.1: {} + + tweetnacl@1.0.3: {} + + type-check@0.3.2: + dependencies: + prelude-ls: 1.1.2 + + type-detect@4.1.0: {} + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@0.7.1: {} + + typechain@8.3.2(typescript@5.8.2): + dependencies: + '@types/prettier': 2.7.3 + debug: 4.4.0(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.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + typedarray@0.0.6: {} + + typescript@5.8.2: {} + + typical@4.0.0: {} + + typical@5.2.0: {} + + uglify-js@3.19.3: + optional: true + + undici-types@6.19.8: {} + + undici-types@6.20.0: {} + + undici@5.28.5: + dependencies: + '@fastify/busboy': 2.1.1 + + undici@6.21.1: {} + + unfetch@4.2.0: {} + + unicorn-magic@0.1.0: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + utf8@3.0.0: {} + + util-deprecate@1.0.2: {} + + uuid@8.3.2: {} + + uuid@9.0.1: {} + + v8-compile-cache-lib@3.0.1: {} + + web3-utils@1.10.4: + dependencies: + '@ethereumjs/util': 8.1.0 + bn.js: 5.2.1 + ethereum-bloom-filters: 1.2.0 + ethereum-cryptography: 2.2.1 + ethjs-unit: 0.1.6 + number-to-bn: 1.7.0 + randombytes: 2.1.0 + utf8: 3.0.0 + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + widest-line@3.1.0: + dependencies: + string-width: 4.2.3 + + word-wrap@1.2.5: {} + + wordwrap@1.0.0: {} + + wordwrapjs@4.0.1: + dependencies: + reduce-flatten: 2.0.0 + typical: 5.2.0 + + workerpool@6.5.1: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@7.5.10: {} + + ws@8.17.1: {} + + ws@8.18.0: {} + + y18n@5.0.8: {} + + yaml@2.7.0: {} + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.2.0: {} diff --git a/remappings.txt b/remappings.txt index f349701..ce46c77 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,3 +2,5 @@ ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ @openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ @openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ +@openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/ +@src/=src/ diff --git a/script-hardhat/create-launchpool.ts b/script-hardhat/create-launchpool.ts new file mode 100644 index 0000000..0e3711d --- /dev/null +++ b/script-hardhat/create-launchpool.ts @@ -0,0 +1,231 @@ +import { ethers } from "hardhat"; + +interface CreateLaunchpoolConfig { + proxyAddress: string; + vAssetAddress: string; + nativeAssetAddress: string; + projectTokenAddress: string; +} + +async function main(config: CreateLaunchpoolConfig) { + const [signer] = await ethers.getSigners(); + console.log("Using signer:", signer.address); + + const contract = await ethers.getContractAt( + "ProjectHubUpgradeable", + config.proxyAddress, + signer, + ); + + // Verify contract owner + const owner = await contract.owner(); + console.log("ProjectHub owner:", owner); + console.log("Is signer owner?", owner.toLowerCase() === signer.address.toLowerCase()); + + // Verify XCM Oracle configuratio + try { + const xcmOracle = await contract.xcmOracleAddress(); + console.log("XCM Oracle address:", xcmOracle); + + // Try to verify the XCM oracle works correctly by calling directly + const mockXCMOracle = await ethers.getContractAt("IXCMOracle", xcmOracle); + + try { + const currencyId = await mockXCMOracle.getCurrencyIdByAssetAddress(config.nativeAssetAddress); + console.log("Currency ID for native asset:", currencyId); + + const poolInfo = await mockXCMOracle.tokenPool(currencyId); + console.log("Pool Info:", { + assetAmount: poolInfo.assetAmount.toString(), + vAssetAmount: poolInfo.vAssetAmount.toString() + }); + } catch (error) { + console.error("Error accessing XCM Oracle functions:", error); + } + } catch (error) { + console.error("Failed to verify XCM Oracle:", error); + } + + // 1. Check if vAsset has a native asset mapping + const nativeAsset = await contract.vAssetToNativeAsset( + config.vAssetAddress, + ); + console.log("Mapped Native Asset:", nativeAsset); + + if (nativeAsset === "0x0000000000000000000000000000000000000000") { + console.log("Setting up vAsset mapping first..."); + const setMappingTx = await contract.setNativeAssetForVAsset( + config.vAssetAddress, + config.nativeAssetAddress, + ); + await setMappingTx.wait(); + console.log("vAsset mapping created!"); + } + + // 2. Create project with dynamic ID tracking + console.log("Creating new project..."); + const createProjectTx = await contract.createProject(); + const receipt = await createProjectTx.wait(); + console.log("Project creation transaction hash:", createProjectTx.hash); + + // Look for project creation event + const projectId = (await contract.nextProjectId()) - 1n; + console.log("Project Created with ID:", projectId); + + // Verify project ownership + const project = await contract.projects(projectId); + console.log("Project owner:", project.projectOwner); + console.log("Is signer project owner?", project.projectOwner.toLowerCase() === signer.address.toLowerCase()); + + // Get current block and set start/end blocks + const currentBlock = BigInt(await ethers.provider.getBlockNumber()); + console.log("Current Block:", currentBlock); + const startBlock = currentBlock + 1000n; + const endBlock = startBlock + 1000n; + console.log("Start Block:", startBlock); + console.log("End Block:", endBlock); + + // Approve project tokens + const projectTokenAmount = ethers.toBigInt("1000000000000000000000000"); + const projectToken = await ethers.getContractAt( + "MockERC20", + config.projectTokenAddress, + signer, + ); + + console.log("Checking project token balance and allowance..."); + const tokenBalance = await projectToken.balanceOf(signer.address); + console.log("Project token balance:", tokenBalance.toString()); + + if (tokenBalance < projectTokenAmount) { + console.log("Minting project tokens..."); + await (await projectToken.freeMint(projectTokenAmount)).wait(); + console.log("Project tokens minted!"); + } + + const currentAllowance = await projectToken.allowance(signer.address, config.proxyAddress); + console.log("Current token allowance:", currentAllowance.toString()); + + if (currentAllowance < projectTokenAmount) { + console.log("Approving project tokens..."); + await ( + await projectToken.approve(config.proxyAddress, projectTokenAmount) + ).wait(); + console.log("Project tokens approved!"); + } + + const params = { + projectId: projectId, + projectTokenAmount: projectTokenAmount, + projectToken: config.projectTokenAddress, + vAsset: config.vAssetAddress, + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: ethers.toBigInt("1000000000000000000"), + changeBlocks: [startBlock, startBlock + 100n], + emissionRateChanges: [ + ethers.toBigInt("1000000000000000000"), + ethers.toBigInt("500000000000000000"), + ], + }; + + console.log("Creating launchpool with params:", { + projectId: Number(params.projectId), + startBlock: Number(params.startBlock), + endBlock: Number(params.endBlock), + vAsset: params.vAsset, + changeBlocksCount: params.changeBlocks.length + }); + + try { + const estimatedGas = await contract.createLaunchpool.estimateGas(params); + console.log("Estimated gas:", estimatedGas.toString()); + + const tx = await contract.createLaunchpool(params, { + gasLimit: estimatedGas * 12n / 10n // Add 20% buffer + }); + console.log("Transaction Hash:", tx.hash); + await tx.wait(); + console.log("Launchpool Created!"); + + // Get newly created launchpool details + try { + const poolId = (await contract.nextPoolId()) - 1n; + const pool = await contract.pools(poolId); + console.log("Created pool details:", { + poolId: Number(pool.poolId), + projectId: Number(pool.projectId), + poolType: pool.poolType, + poolAddress: pool.poolAddress + }); + } catch (error) { + console.error("Error fetching pool details:", error); + } + } catch (error) { + console.error("Failed to create launchpool:"); + + if (error.error && error.error.data) { + // For lower level revert reasons + console.error("Error data:", error.error.data); + } + + // Extract meaningful error message from revert + if ((error as any).message) { + console.error("Error message:", (error as any).message); + + if ((error as any).message.includes("reverted")) { + const match = (error as any).message.match( + /reverted with reason string '([^']+)'/, + ); + if (match) { + console.error("Revert reason:", match[1]); + } else if ((error as any).message.includes("reverted with custom error")) { + console.error("Reverted with custom error"); + } else if ((error as any).message.includes("reverted with panic code")) { + const panicMatch = (error as any).message.match(/reverted with panic code 0x([0-9a-f]+)/); + if (panicMatch) { + const panicCode = panicMatch[1]; + console.error(`Panic code: 0x${panicCode}`); + // Interpret panic code + const panicReasons: Record = { + "01": "Assert failed", + "11": "Arithmetic overflow/underflow", + "12": "Division by zero", + "21": "Invalid enum value", + "22": "Storage access out of bounds", + "31": "Pop from empty array", + "32": "Array index out of bounds", + "41": "Memory overflow", + "51": "Zero initialized variable" + }; + console.error(`Panic reason: ${panicReasons[panicCode] || "Unknown panic code"}`); + } + } + } + } + + // Try to find more specific information about why the transaction might have failed + if ((error as any).transaction) { + console.log("Trying to simulate the failed transaction to get more details..."); + try { + const provider = ethers.provider; + provider.call({ + to: (error as any).transaction.to, + data: (error as any).transaction.data, + from: (error as any).transaction.from, + }).catch((callError) => { + console.error("Simulated call error:", callError); + }); + } catch (simulationError) { + console.error("Error during transaction simulation:", simulationError); + } + } + } +} + +main({ + proxyAddress: "0xD1b11fE68a7e363E5564aB86AB496Ec9C4eB125d", + vAssetAddress: "0xD02D73E05b002Cb8EB7BEf9DF8Ed68ed39752465", + nativeAssetAddress: "0x7a4ebae8cA815b9F52F23a8AC9A2f707D4d4ff81", + projectTokenAddress: "0x96b6D28DF53641A47be72F44BE8C626bf07365A8", +}).catch(console.error); diff --git a/script-hardhat/deploy-mock-erc20.ts b/script-hardhat/deploy-mock-erc20.ts new file mode 100644 index 0000000..ab91201 --- /dev/null +++ b/script-hardhat/deploy-mock-erc20.ts @@ -0,0 +1,61 @@ +import { ethers } from "hardhat"; +import { logDeployment, getLatestCommitHash } from "./utils"; + +async function main() { + const chainId = await ethers.provider + .getNetwork() + .then((n) => Number(n.chainId)); + const [signer] = await ethers.getSigners(); + const deployerAddress = await signer.getAddress(); + const latestCommitHash = getLatestCommitHash(); + + const vFactory = await ethers.getContractFactory("MockERC20", signer); + const vContract = await vFactory.deploy("Voucher Imagination", "VI"); + await vContract.waitForDeployment(); + const vAddress = await vContract.getAddress(); + console.log(`Voucher Imagination deployed at: ${vAddress}`); + logDeployment(chainId, { + name: "MockVToken", + type: "contract", + address: vAddress, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + commitHash: latestCommitHash, + version: "increment", + isUpgradeSafe: false, + }); + + const nFactory = await ethers.getContractFactory("MockERC20", signer); + const nContract = await nFactory.deploy("Native Token", "NAT"); + await nContract.waitForDeployment(); + const nAddress = await nContract.getAddress(); + console.log(`Native token deployed at: ${nAddress}`); + logDeployment(chainId, { + name: "MockNativeToken", + type: "contract", + address: nAddress, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + commitHash: latestCommitHash, + version: "increment", + isUpgradeSafe: false, + }); + + const pFactory = await ethers.getContractFactory("MockERC20", signer); + const pContract = await pFactory.deploy("Project Token", "PRO"); + await pContract.waitForDeployment(); + const pAddress = await pContract.getAddress(); + console.log(`Project token deployed at: ${pAddress}`); + logDeployment(chainId, { + name: "MockProjectToken", + type: "contract", + address: pAddress, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + commitHash: latestCommitHash, + version: "increment", + isUpgradeSafe: false, + }); +} + +main().catch((err) => console.error(err)); diff --git a/script-hardhat/deploy-mock-xcm-oracle.ts b/script-hardhat/deploy-mock-xcm-oracle.ts new file mode 100644 index 0000000..24932fc --- /dev/null +++ b/script-hardhat/deploy-mock-xcm-oracle.ts @@ -0,0 +1,80 @@ +import { ethers } from "hardhat"; +import { logDeployment, getLatestCommitHash } from "./utils"; + +async function main() { + console.log("Deploying MockXCMOracle to Moonbase Alpha..."); + + // Check if we're on the correct network + const network = await ethers.provider.getNetwork(); + const chainId = Number(network.chainId); + + if (chainId !== 1287) { + console.warn( + `Warning: Expected Moonbase Alpha (1287), but connected to chain ID ${chainId}`, + ); + // throw new Error(`Expected Moonbase Alpha (1287), but connected to chain ID ${chainId}`); + } + + const [deployer] = await ethers.getSigners(); + console.log(`Deploying contracts with the account: ${deployer.address}`); + + // Moonbase Alpha block time is ~6seconds + const MOONBEAM_BLOCK_TIME = 6; + + // Constructor parameters + const initialRate = ethers.parseEther("1.0"); // Initial exchange rate 1.0 + const blockInterval = 10n; // Update exchange rate every 10 blocks + const apy = 100_000n; // 10% APY (10.0000%) + + // Deploy the contract + const MockXCMOracle = await ethers.getContractFactory("MockXCMOracle"); + const mockXCMOracle = await MockXCMOracle.deploy( + initialRate, + blockInterval, + apy, + MOONBEAM_BLOCK_TIME, + ); + + await mockXCMOracle.waitForDeployment(); + const address = await mockXCMOracle.getAddress(); + + console.log(`MockXCMOracle deployed to: ${address}`); + console.log("Deployment parameters:"); + console.log( + `- Initial rate: ${ethers.formatEther(initialRate)} (${initialRate})`, + ); + console.log(`- Block interval: ${blockInterval}`); + console.log(`- APY: ${Number(apy) / 10_000}%`); + console.log(`- Network block time: ${MOONBEAM_BLOCK_TIME} seconds`); + + // Log deployment information + const deployerAddress = await deployer.getAddress(); + const latestCommitHash = getLatestCommitHash(); + + logDeployment(chainId, { + name: "MockXCMOracle", + type: "contract", + address: address, + commitHash: latestCommitHash, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + version: "v1", + isUpgradeSafe: false, + constructorArgs: { + _initialRate: initialRate.toString(), + _blockInterval: blockInterval.toString(), + _apy: apy.toString(), + _networkBlockTime: MOONBEAM_BLOCK_TIME, + }, + }); + + // Return the address for testing purposes + return address; +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/script-hardhat/deploy-project-hub-proxy.ts b/script-hardhat/deploy-project-hub-proxy.ts new file mode 100644 index 0000000..0ff6c8d --- /dev/null +++ b/script-hardhat/deploy-project-hub-proxy.ts @@ -0,0 +1,189 @@ +import { ethers, upgrades } from "hardhat"; +import { logDeployment } from "./utils"; +import { preDeploymentCheck, getLatestCommitHash } from "./utils"; +import { getNamedFunctionArgs } from "./utils"; +import { ProjectHubUpgradeable__factory } from "../typechain-types"; + +// Define the configuration object type for deployProjectHubProxy +interface DeployProjectHubProxyConfig { + vAssets: string[]; + nativeAssets: string[]; + xcmOracleAddress: string; + projectLibAddress?: string; + launchpoolLibAddress?: string; +} + +async function deployProjectHubProxy(config: DeployProjectHubProxyConfig) { + let { + vAssets, + nativeAssets, + xcmOracleAddress, + projectLibAddress, + launchpoolLibAddress, + } = config; + + const chainId = await ethers.provider + .getNetwork() + .then((n) => Number(n.chainId)); + // preDeploymentCheck(chainId); TODO: Turn this on later + + const [deployer] = await ethers.getSigners(); + const deployerAddress = await deployer.getAddress(); + const latestCommitHash = getLatestCommitHash(); + + // Deploy libraries + console.log("Deploying libraries..."); + + let projectLib; + if (!!projectLibAddress) { + projectLib = await ethers.getContractAt( + "ProjectLibrary", + projectLibAddress, + ); + console.log("ProjectLib retrieved from address: ", projectLibAddress); + } else { + const projectLibFactory = + await ethers.getContractFactory("ProjectLibrary"); + projectLib = await projectLibFactory.deploy(); + projectLib.waitForDeployment(); + projectLibAddress = await projectLib.getAddress(); + console.log("ProjectLib deployed to: ", projectLibAddress); + // Log deployment info for ProjectLib + logDeployment(chainId, { + name: "ProjectLibrary", + type: "library", + address: projectLibAddress, + commitHash: latestCommitHash, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + version: "increment", + isUpgradeSafe: true, + }); + } + + let launchpoolLib; + if (!!launchpoolLibAddress) { + launchpoolLib = await ethers.getContractAt( + "LaunchpoolLibrary", + launchpoolLibAddress, + ); + console.log( + "LaunchpoolLib retrieved from address: ", + launchpoolLibAddress, + ); + } else { + const launchpoolLibFactory = + await ethers.getContractFactory("LaunchpoolLibrary"); + launchpoolLib = await launchpoolLibFactory.deploy(); + await launchpoolLib.waitForDeployment(); + launchpoolLibAddress = await launchpoolLib.getAddress(); + console.log("Launchpool library deployed to:", launchpoolLibAddress); + // Log deployment info for LaunchpoolLibrary + logDeployment(chainId, { + name: "LaunchpoolLibrary", + type: "library", + address: launchpoolLibAddress, + commitHash: latestCommitHash, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + version: "increment", + isUpgradeSafe: true, + }); + } + + // Create ProjectHubFactory and link libraries + const ProjectHubFactory = await ethers.getContractFactory( + "ProjectHubUpgradeable", + { + libraries: { + ProjectLibrary: await projectLib.getAddress(), + LaunchpoolLibrary: await launchpoolLib.getAddress(), + }, + }, + ); + + // Deploy ProjectHubUpgradeable proxy + console.log("Deploying ProjectHub proxy..."); + // Include XCMOracle address in initialization arguments + const projectHubInitArgs = [ + xcmOracleAddress, + deployerAddress, + vAssets, + nativeAssets, + ]; + const projectHubProxy = await upgrades.deployProxy( + ProjectHubFactory, + projectHubInitArgs, + { + initializer: "initialize", + kind: "transparent", + unsafeAllow: ["external-library-linking"], + }, + ); + await projectHubProxy.waitForDeployment(); + const projectHubProxyAddress = await projectHubProxy.getAddress(); + console.log( + "ProjectHubUpgradeable proxy deployed to:", + projectHubProxyAddress, + ); + + // After deployment + const adminAddress = await upgrades.erc1967.getAdminAddress( + await projectHubProxy.getAddress(), + ); + const implAddress = await upgrades.erc1967.getImplementationAddress( + await projectHubProxy.getAddress(), + ); + + // Log deployment info for ProjectHub + logDeployment(chainId, { + name: "ProjectHubUpgradable", + type: "contract", + address: implAddress, + commitHash: latestCommitHash, + deploymentTime: new Date().toISOString(), + deployer: deployerAddress, + version: "v1", + linkedLibraries: { + ProjectLibrary: projectLibAddress, + LaunchpoolLibrary: launchpoolLibAddress, + }, + isUpgradeSafe: true, + upgradeability: { + pattern: "transparent", + proxyAddress: projectHubProxyAddress, + proxyAdminAddress: adminAddress, + implementationAddress: implAddress, + initializerArgs: await getNamedFunctionArgs( + ProjectHubUpgradeable__factory as any, + "initialize", + projectHubInitArgs, + ), + }, + }); + + return projectHubProxy; +} + +async function main() { + try { + // Now deploy the ProjectHub with the MockXCMOracle address using the new config object + await deployProjectHubProxy({ + vAssets: ["0xD02D73E05b002Cb8EB7BEf9DF8Ed68ed39752465"], // Voucher Imagination + nativeAssets: ["0x7a4ebae8cA815b9F52F23a8AC9A2f707D4d4ff81"], // Native Token + xcmOracleAddress: "0x288154C87Db809bc0d702CB46De40E5041b22071", // XCM Oracle + projectLibAddress: "0x8BDB2E6F6dD2172178BCba5529C3D5dFe96B1538", // Project library + launchpoolLibAddress: "0xe7F3843639DFFd610176327C5Eb5220F44a5cF9C", // Launchpool library + }); + } catch (error) { + console.error("Deployment failed:", error); + process.exit(1); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/script-hardhat/types/DeploymentInfo.d.ts b/script-hardhat/types/DeploymentInfo.d.ts new file mode 100644 index 0000000..aa61fe2 --- /dev/null +++ b/script-hardhat/types/DeploymentInfo.d.ts @@ -0,0 +1,35 @@ +/** + * Deployment info for a contract or library. + * This is a structured deployment info that can be saved to a file. + */ +export interface DeploymentInfo { + name: string; // Contract/Library name + type: "contract" | "library"; + address: string; // Deployed address + commitHash: string; // Git commit hash (for improved tracing of code changes) + deploymentTime: string; // ISO timestamp (e.g. "2025-01-01T00:00:00Z") + deployer: string; // Deployer address + constructorArgs?: Record; // Constructor arguments + linkedLibraries?: { + // Externally linked libraries (if any) + [libraryName: string]: string; // Library name -> address, e.g. {"ProjectLibrary": "0x1234..."} + }; + version: `v${number}` | "increment"; // Version tag (v1, v2, etc.) or "increment" for auto-increment + + // Upgradeable-specific info: + isUpgradeSafe: boolean; // Is this contract/library upgrade-safe? + upgradeability?: { + pattern: "transparent" | "uups" | "diammond" | "beacon"; // Upgradeable pattern + proxyAddress?: string; // Proxy address (if applicable) + proxyAdminAddress?: string; // Proxy admin contract address (if applicable) + adminAddress?: string; // Admin address (if applicable) + implementationAddress?: string; // Implementation address (if applicable) + initializerArgs?: Record; // Initializer arguments (if applicable) + }; + + // Additional metadata + verified?: boolean; // Whether verified on block explorer + license?: string; // License type + abi?: any[]; // Contract ABI + bytecode?: string; // Contract bytecode +} diff --git a/script-hardhat/types/index.ts b/script-hardhat/types/index.ts new file mode 100644 index 0000000..b2f28df --- /dev/null +++ b/script-hardhat/types/index.ts @@ -0,0 +1 @@ +export * from "./DeploymentInfo"; \ No newline at end of file diff --git a/script-hardhat/utils.ts b/script-hardhat/utils.ts new file mode 100644 index 0000000..508d738 --- /dev/null +++ b/script-hardhat/utils.ts @@ -0,0 +1,294 @@ +import fs from "fs"; +import path from "path"; +import { DeploymentInfo } from "./types"; +import { + ContractFactory, + ParamType, + Interface, + FunctionFragment, +} from "ethers"; +import { execSync } from "child_process"; +import chainManifest from "../chain-manifest.json"; + +// Log deployment info to a JSON file +export function logDeployment( + chainId: number, + deploymentInfo: DeploymentInfo, + logOptions?: { + writeAbiToPath?: string; // e.g. write ABI to front-end's dir + writeBytecodeToPath?: string; + }, +) { + // Create directories if they don't exist + const chain = + chainManifest[chainId.toString() as keyof typeof chainManifest]; + const chainDir = path.join( + "./deployments", + chainId.toString() + "_" + chain.name, + ); + if (!fs.existsSync(chainDir)) { + fs.mkdirSync(chainDir, { recursive: true }); + } + + // Read existing JSON deployment info file + const filePath = getDeploymentInfoPath(chainId, deploymentInfo.name); + if (!fs.existsSync(filePath)) { + fs.writeFileSync(filePath, "[]"); + } + + // Validate upgradeable contract version + if (deploymentInfo.version) { + const latestVersion = getLatestContractVersion( + chainId, + deploymentInfo.name, + ); + if (deploymentInfo.version === "increment") { + deploymentInfo.version = ("v" + + String(latestVersion + 1)) as `v${number}`; + } + if (!deploymentInfo.version.startsWith("v")) + throw new Error(`Invalid version tag: ${deploymentInfo.version}`); + + const version = parseInt(deploymentInfo.version.slice(1)); + if (version <= latestVersion) + throw new Error( + `Version ${version} is not greater than the latest version.`, + ); + } + + const existingDeployments = ( + JSON.parse(fs.readFileSync(filePath, "utf8")) + ); + + // Append to JSON file + existingDeployments.push(deploymentInfo); + fs.writeFileSync(filePath, JSON.stringify(existingDeployments, null, 4)); + + // TODO: implement log options + + console.log( + `Deployment info of ${deploymentInfo.name} logged to file:`, + filePath, + ); +} + +export function preDeploymentCheck(chainId: number) { + // Check if there are uncommitted changes to the .sol files + // if deploying to a non-local chain + const isLocalChain = + chainManifest[chainId.toString() as keyof typeof chainManifest].type === + "local"; + if (isLocalChain) return; + + const output = execSync("git status -s src/").toString(); + + if (output.trim()) { + const uncommittedFiles = output + .split("\n") + .filter((line) => line.trim() && line.includes(".sol")) + .map((line) => line.trim()); + + if (uncommittedFiles.length > 0) { + console.warn( + "โš ๏ธ DEADLY WARNING: You have uncommitted changes in Solidity files:", + ); + uncommittedFiles.forEach((file) => console.warn(` ${file}`)); + console.warn( + "It's recommended to build, test, commit your changes before deployment.", + ); + + throw new Error("Cannot deploy with uncommitted Solidity files."); + } + } else { + console.log("โœ“ All Solidity files are committed."); + } +} + +export function getLatestCommitHash(): string { + const commitHash = require("child_process") + .execSync("git rev-parse HEAD") + .toString() + .trim(); + return commitHash; +} + +export function isChainSupported(chainId: number): boolean { + return Object.keys(chainManifest).includes(chainId.toString()); +} + +export function isContractDeployedToChain( + chainId: number, + contractOrLibName: string, +): boolean { + if (!isChainSupported(chainId)) { + throw new Error(`Chain ID ${chainId} is not supported.`); + } + const deploymentInfoPath = getDeploymentInfoPath( + chainId, + contractOrLibName, + ); + return fs.existsSync(deploymentInfoPath); +} + +export function getDeploymentInfoPath( + chainId: number, + contractOrLibName: string, +): string { + if (!isChainSupported(chainId)) { + throw new Error(`Chain ID ${chainId} is not supported.`); + } + + const chain = + chainManifest[chainId.toString() as keyof typeof chainManifest]; + return path.join( + "./deployments", + chainId.toString() + "_" + chain.name, + `${contractOrLibName}.json`, + ); +} + +export function getLatestContractVersion( + chainId: number, + contractOrLibName: string, +): number { + if (!isChainSupported(chainId)) { + throw new Error(`Chain ID ${chainId} is not supported.`); + } + + const chainIdStr = chainId.toString(); + const chain = chainManifest[chainIdStr]; + + // For first deployment, return 0 instead of throwing an error + if (!isContractDeployedToChain(chainId, contractOrLibName)) { + console.log( + `First deployment of ${contractOrLibName} on chain ${chainId} (${chain.name})`, + ); + return 0; + } + + try { + const deploymentInfoPath = getDeploymentInfoPath( + chainId, + contractOrLibName, + ); + const fileContent = fs.readFileSync(deploymentInfoPath, "utf8"); + + // Handle empty files + if (!fileContent.trim()) { + return 0; + } + + const deployments = JSON.parse(fileContent); + + // Handle empty arrays + if (!deployments || deployments.length === 0) { + return 0; + } + + // Find highest version + // let highestVersion = 0; + const newestDeployment = deployments.reduce( + (newestDeployment, currDeployment) => { + const newestVersion = parseInt( + newestDeployment.version.slice(1), + ); + const currVersion = parseInt(currDeployment.version.slice(1)); + return currVersion > newestVersion + ? currDeployment + : newestDeployment; + }, + deployments[0], + ); + const newestVersion = parseInt(newestDeployment.version.slice(1)); + // for (const info of deployments) { + // try { + // const version = parseInt(info.version.slice(1)); + // if (!isNaN(version) && version > highestVersion) { + // highestVersion = version; + // } + // } catch (e) { + // console.error(`Error parsing version: ${info.version}`); + // } + // } + + console.log( + `Found highest version ${newestVersion} for ${contractOrLibName}`, + ); + return newestVersion; + } catch (error) { + console.error(`Error reading deployment info: ${error}`); + return 0; // Default to 0 on error + } +} + +/** + * + * @param contractFactory + * @param functionNameOrSig + * @param args + * @returns + */ +export async function getNamedFunctionArgs< + TypechainContractFactory extends ContractFactory, + FunctionNameOrSig extends string, +>( + contractFactory: TypechainContractFactory, + functionNameOrSig: FunctionNameOrSig, + args: any[], +): Promise | undefined> { + try { + let fragment; + + // Special handling for constructor + if (functionNameOrSig.toLowerCase() === "constructor") { + // Access the ABI directly to find the constructor + const contractName = (contractFactory as any).name.replace( + "__factory", + "", + ); + const abi = require( + path.join( + "../out", + `${contractName}.sol`, + `${contractName}.json`, + ), + ).abi; + + // Find constructor in the ABI + fragment = abi.find((item: any) => item.type === "constructor"); + } else { + // Normal function - use interface + const contractIface = ( + contractFactory as any + ).createInterface() as Interface; + fragment = contractIface.getFunction(functionNameOrSig as string); + } + + if (!fragment) { + throw new Error( + `Function ${functionNameOrSig} not found in interface.`, + ); + } + + // Extract parameter names from function fragment + const inputs = (fragment as FunctionFragment).inputs || []; + if (inputs.length !== args.length) { + throw new Error( + `Incorrect number of arguments for function ${functionNameOrSig}: ${args.length} provided, ${inputs.length} expected.`, + ); + } + + const paramNames = inputs.map( + (input: ParamType) => input.name || "unnamed", + ); + + // Create structured arguments + return Object.fromEntries( + paramNames.map((name: string, i: number) => [name, args[i]]), + ); + } catch (error) { + console.error(`Error in getNamedFunctionArgs: ${error}`); + // Fallback to simple numbered arguments if all else fails + // return Object.fromEntries(args.map((arg, i) => [`arg${i + 1}`, arg])); + } +} diff --git a/script/DeployLaunchpoolWithMocks.s.sol b/script/DeployLaunchpoolWithMocks.s.sol new file mode 100644 index 0000000..55af4ff --- /dev/null +++ b/script/DeployLaunchpoolWithMocks.s.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import { Script, console2 } from "forge-std/Script.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; + +/** + * @title DeployLaunchpoolWithMocksScript + * @notice A script to deploy a Launchpool with mock dependencies for testing purposes, due to testing native token is also reward token + */ +contract DeployLaunchpoolWithMocksScript is Script { + function run() public { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_DEV_KEY"); + vm.startBroadcast(deployerPrivateKey); + + // Deploy Mock XCM Oracle + // Parameters: initialRate (1:1), blockInterval (1), apy (5%), networkBlockTime (12 seconds) + MockXCMOracle mockXCMOracle = new MockXCMOracle( + 1e18, // Initial 1:1 exchange rate + 1, // Update every block + 50_000, // 5% APY (with 6 decimals of precision) + 12 // 12 second block time + ); + + // Deploy Mock DOT and vDOT tokens + MockERC20 dotToken = new MockERC20("Dot", "DOT"); + MockERC20 vDotToken = new MockERC20("Voucher Dot", "vDOT"); + + // Set both tokens to have 12 decimals (matching DOT's decimals) + dotToken.setDecimals(12); + vDotToken.setDecimals(12); + + // Pre-mint some tokens to the deployer + uint256 initialMint = 1_000_000 * 10 ** 12; // 1 million tokens + dotToken.freeMint(initialMint); + vDotToken.freeMint(initialMint); + + // Calculate blocks for the Launchpool duration + uint128 currentBlock = uint128(block.number); + uint128 startBlock = currentBlock + 100; // Start 100 blocks from now + uint128 endBlock = startBlock + 50_000; // Run for 50,000 blocks (about 1 week at 12 sec blocks) + + // Prepare change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](3); + uint256[] memory emissionRates = new uint256[](3); + + // Configure emission schedule + changeBlocks[0] = startBlock; // Start with initial rate + changeBlocks[1] = startBlock + 25_000; // Change halfway through + changeBlocks[2] = endBlock - 10_000; // Change near the end + + emissionRates[0] = 10 * 10 ** 12; // 10 tokens per block initially + emissionRates[1] = 5 * 10 ** 12; // 5 tokens per block in the middle + emissionRates[2] = 2 * 10 ** 12; // 2 tokens per block at the end + + // Maximum tokens per staker (100,000 DOT) + uint256 maxTokenPerStaker = 100_000 * 10 ** 12; + + // Deploy Launchpool + Launchpool launchpool = new Launchpool( + address(mockXCMOracle), + msg.sender, // Project owner + address(dotToken), // Project token is DOT + address(vDotToken), // Accepted vAsset is vDOT + address(dotToken), // Native asset is DOT + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRates + ); + + // Mint DOT tokens to the Launchpool for rewards + // Calculate total emission based on schedule + uint256 totalEmission = emissionRates[0] * + (changeBlocks[1] - changeBlocks[0]) + + emissionRates[1] * + (changeBlocks[2] - changeBlocks[1]) + + emissionRates[2] * + (endBlock - changeBlocks[2]); + + // Add a 10% buffer to ensure there are enough tokens + uint256 tokensToMint = (totalEmission * 110) / 100; + dotToken.freeMintTo(address(launchpool), tokensToMint); + + vm.stopBroadcast(); + + // Log the deployed contract addresses + console2.log("Deployed contracts:"); + console2.log("-------------------"); + console2.log("MockXCMOracle: ", address(mockXCMOracle)); + console2.log("DOT Token: ", address(dotToken)); + console2.log("vDOT Token: ", address(vDotToken)); + console2.log("Launchpool: ", address(launchpool)); + console2.log("-------------------"); + console2.log("Launchpool Configuration:"); + console2.log("Start Block: ", startBlock); + console2.log("End Block: ", endBlock); + console2.log("Total Emission: ~", totalEmission / 10 ** 12, " DOT"); + console2.log( + "Max Token Per Staker: ", + maxTokenPerStaker / 10 ** 12, + " DOT" + ); + } +} diff --git a/src/LaunchPool.sol b/src/LaunchPool.sol deleted file mode 100644 index 337373e..0000000 --- a/src/LaunchPool.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; - -contract LaunchPool is Ownable, ReentrancyGuard { - ///////////////////////////////////////////////////////////////// - //////////////////////// CONTRACT STATES /////////////////////// - /////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////// - //////////////////////// CONTRACT EVENTS /////////////////////// - /////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////// - ////////////////// VALIDATE POOL INFO ERRORS /////////////////// - /////////////////////////////////////////////////////////////// - error StartTimeMustBeInFuture(); - error EndTimeMustBeAfterStartTime(); - error InvalidProjectTokenAddress(); - error InvalidAcceptedVAssetAddress(); - error TotalProjectTokensMustBeGreaterThanZero(); - error MaxAndMinTokensPerStakerMustBeGreaterThanZero(); - - ////////////////////////////////////////////////////////////////////////// - /////////////////////////////// MODIFIERS /////////////////////////////// - //////////////////////////////////////////////////////////////////////// - modifier validTimeFrame(uint256 _startTime, uint256 _endTime) { - if (_startTime <= block.timestamp) revert StartTimeMustBeInFuture(); - if (_endTime <= _startTime) revert EndTimeMustBeAfterStartTime(); - _; - } - - modifier validAddresses(address _projectToken, address _acceptedVAsset) { - if (_projectToken == address(0)) revert InvalidProjectTokenAddress(); - if (_acceptedVAsset == address(0)) - revert InvalidAcceptedVAssetAddress(); - _; - } - - modifier validTokenAmounts( - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) { - if (_totalProjectTokens == 0) - revert TotalProjectTokensMustBeGreaterThanZero(); - if (_maxVTokensPerStaker == 0 || _minVTokensPerStaker == 0) - revert MaxAndMinTokensPerStakerMustBeGreaterThanZero(); - _; - } - - constructor( - address _projectOwner, - address _projectToken, - address _acceptedVAsset, - uint256 _startTime, - uint256 _endTime, - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) Ownable(_projectOwner) { - _initValidation( - _projectToken, - _acceptedVAsset, - _startTime, - _endTime, - _totalProjectTokens, - _maxVTokensPerStaker, - _minVTokensPerStaker - ); - } - - function _initValidation( - address _projectToken, - address _acceptedVAsset, - uint256 _startTime, - uint256 _endTime, - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) - internal - view - validTimeFrame(_startTime, _endTime) - validAddresses(_projectToken, _acceptedVAsset) - validTokenAmounts( - _totalProjectTokens, - _maxVTokensPerStaker, - _minVTokensPerStaker - ) - returns (bool) - { - return true; - } -} diff --git a/src/LaunchPoolFactory.sol b/src/LaunchPoolFactory.sol deleted file mode 100644 index d2d3f33..0000000 --- a/src/LaunchPoolFactory.sol +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { LaunchPool } from "./LaunchPool.sol"; - -contract LaunchPoolFactory is Ownable { - ///////////////////////////////////////////////////////////////// - //////////////////////// CONTRACT STATES /////////////////////// - /////////////////////////////////////////////////////////////// - // Counter for pool IDs - uint256 private _nextPoolId; - - // Mapping from pool ID => pool address - mapping(uint256 => address) public pools; - - // Mapping from project pool address => is valid/not valid || Check whether the pool is derived from this contract - mapping(address => bool) internal _poolIsValid; - - ///////////////////////////////////////////////////////////////// - //////////////////////// CONTRACT EVENTS /////////////////////// - /////////////////////////////////////////////////////////////// - event PoolCreated( - uint256 indexed poolId, - address indexed projectOwner, - address indexed projectToken, - address acceptedVAsset, - address poolAddress, - uint256 startTime, - uint256 endTime - ); - - ///////////////////////////////////////////////////////////////// - //////////////////////// CONTRACT ERRORS /////////////////////// - /////////////////////////////////////////////////////////////// - error InvalidPoolId(); - error StartTimeMustBeInFuture(); - error EndTimeMustBeAfterStartTime(); - error InvalidProjectTokenAddress(); - error InvalidAcceptedVAssetAddress(); - error InvalidTokenAmount(); - - ////////////////////////////////////////////////////////////////////////// - /////////////////////////////// MODIFIERS /////////////////////////////// - //////////////////////////////////////////////////////////////////////// - modifier isValidPoolId(uint256 poolId) { - if (poolId >= _nextPoolId) { - revert InvalidPoolId(); - } - _; - } - modifier validTimeFrame(uint256 _startTime, uint256 _endTime) { - if (_startTime <= block.timestamp) revert StartTimeMustBeInFuture(); - if (_endTime <= _startTime) revert EndTimeMustBeAfterStartTime(); - _; - } - - modifier validAddresses(address _projectToken, address _acceptedVAsset) { - if (_projectToken == address(0)) revert InvalidProjectTokenAddress(); - if (_acceptedVAsset == address(0)) - revert InvalidAcceptedVAssetAddress(); - _; - } - - modifier validTokenAmounts( - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) { - if ( - (_totalProjectTokens == 0 || - _maxVTokensPerStaker == 0 || - _minVTokensPerStaker == 0) || - (_maxVTokensPerStaker < _minVTokensPerStaker) - ) revert InvalidTokenAmount(); - _; - } - - constructor() Ownable(_msgSender()) { - _nextPoolId = 1; // Start pool IDs from 1 - } - - function createPool( - address _projectToken, - address _acceptedVAsset, - uint256 _startTime, - uint256 _endTime, - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) public returns (uint256 poolId) { - _initValidation( - _projectToken, - _acceptedVAsset, - _startTime, - _endTime, - _totalProjectTokens, - _maxVTokensPerStaker, - _minVTokensPerStaker - ); - - poolId = _nextPoolId++; - - address poolAddress = address( - new LaunchPool( - _msgSender(), - _projectToken, - _acceptedVAsset, - _startTime, - _endTime, - _totalProjectTokens, - _maxVTokensPerStaker, - _minVTokensPerStaker - ) - ); - - pools[poolId] = poolAddress; - _poolIsValid[poolAddress] = true; - - emit PoolCreated( - poolId, - msg.sender, - _projectToken, - _acceptedVAsset, - poolAddress, - _startTime, - _endTime - ); - - return poolId; - } - - ////////////////////////////////////////////////////////////////////////// - //////////////////////// REGULAR VIEW FUNCTIONS ///////////////////////// - //////////////////////////////////////////////////////////////////////// - function getPoolAddress( - uint256 poolId - ) public view isValidPoolId(poolId) returns (address) { - return pools[poolId]; - } - - function isPoolValid(address poolAddress) public view returns (bool) { - return _poolIsValid[poolAddress]; - } - - function getPoolCount() public view returns (uint256) { - return _nextPoolId - 1; - } - - function _initValidation( - address _projectToken, - address _acceptedVAsset, - uint256 _startTime, - uint256 _endTime, - uint256 _totalProjectTokens, - uint256 _maxVTokensPerStaker, - uint256 _minVTokensPerStaker - ) - internal - view - validTimeFrame(_startTime, _endTime) - validAddresses(_projectToken, _acceptedVAsset) - validTokenAmounts( - _totalProjectTokens, - _maxVTokensPerStaker, - _minVTokensPerStaker - ) - returns (bool) - { - return true; - } -} diff --git a/src/interfaces/ILaunchpool.sol b/src/interfaces/ILaunchpool.sol new file mode 100644 index 0000000..67eacde --- /dev/null +++ b/src/interfaces/ILaunchpool.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +interface ILaunchpool { + // Structs + struct Staker { + uint256 vAssetAmount; + uint256 nativeTokenAmount; + uint256 claimOffset; + } + + // Events + event Staked(address indexed user, uint256 amount); + event Unstaked(address indexed user, uint256 amount); + + // Functions + function stake(uint256 _amount) external; + + function unstake(uint256 _amount) external; + + function unstakeWithoutProjectToken() external; + + function recoverWrongToken(address _tokenAddress) external; + + function claimLeftoverProjectToken() external; + + function claimOwnerInterest() external; + + function claimPlatformInterest() external; + + function setXCMOracleAddress(address _xcmOracleAddress) external; + + // View Functions + function owner() external view returns (address); + + function getPoolInfo() + external + view + returns (uint128, uint128, uint256, uint256); // startBlock, endBlock, totalProjectToken, emissionRate + + function getTotalStaked() external view returns (uint256); + + function getTotalProjectToken() external view returns (uint256); + + function getStakingRange() external view returns (uint256, uint256); // maxVAssetPerStaker, maxStakers + + function getEmissionRate() external view returns (uint256); + + function getClaimableProjectToken( + address _investor + ) external view returns (uint256); + + // State Variables + function cumulativeExchangeRate() external view returns (uint256); + + function startBlock() external view returns (uint128); + + function endBlock() external view returns (uint128); + + function tickBlock() external view returns (uint128); + + function ownerShareOfInterest() external view returns (uint128); + + function maxVAssetPerStaker() external view returns (uint256); + + function maxStakers() external view returns (uint256); + + // solhint-disable-next-line + function SCALING_FACTOR() external view returns (uint256); + + function lastProcessedChangeBlockIndex() external view returns (uint256); + + function platformAdminAddress() external view returns (address); + + function changeBlocks(uint256 index) external view returns (uint128); + + function emissionRateChanges( + uint128 blockNumber + ) external view returns (uint256); + + function projectToken() external view returns (address); + + function acceptedVAsset() external view returns (address); + + function xcmOracle() external view returns (address); + + function stakers(address user) external view returns (Staker memory); +} diff --git a/src/interfaces/IProjectHub.sol b/src/interfaces/IProjectHub.sol new file mode 100644 index 0000000..f3f8abb --- /dev/null +++ b/src/interfaces/IProjectHub.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +/** + * @title IProjectHub + * @notice Interface for the ProjectHubUpgradeable contract + * @dev This interface is self-contained without external dependencies for easier integration with tools like Remix IDE + */ +interface IProjectHub { + // Type definitions + enum PoolType { + LAUNCHPOOL, + LAUNCHPAD, + VESTING, + FARMING + } + + struct Project { + uint64 projectId; + address projectOwner; + } + + struct Pool { + uint64 poolId; + PoolType poolType; + address poolAddress; + uint64 projectId; + } + + struct LaunchpoolCreationParams { + uint64 projectId; + uint256 projectTokenAmount; + address projectToken; + address vAsset; + uint128 startBlock; + uint128 endBlock; + uint256 maxVTokensPerStaker; + uint128[] changeBlocks; + uint256[] emissionRateChanges; + } + + // Events + event ProjectCreated( + uint64 indexed projectId, + address indexed projectOwner + ); + event LaunchpoolCreated( + uint64 indexed projectId, + PoolType indexed poolType, + uint64 poolId, + address projectToken, + address indexed vAsset, + address poolAddress, + uint128 startBlock, + uint128 endBlock + ); + event VAssetMappingUpdated( + address indexed vAsset, + address indexed nativeAsset + ); + + // Initialization & Admin Functions + function initialize( + address _initialOwner, + address[] calldata _initialVAssets, + address[] calldata _initialNativeAssets + ) external; + + function setNativeAssetForVAsset( + address _vAsset, + address _nativeAsset + ) external; + + function removeVAssetSupport(address _vAsset) external; + + // Project Management + function createProject() external; + + // Pool Management + function createLaunchpool( + LaunchpoolCreationParams memory params + ) external returns (uint64); + + // Multi-call Functionality + function selfMultiCall( + bytes[] calldata data + ) external returns (bytes[] memory); + + // View Functions - State Variables + function projects(uint64 projectId) external view returns (Project memory); + + function pools(uint64 poolId) external view returns (Pool memory); + + function vAssetToNativeAsset( + address _vAsset + ) external view returns (address); + + function nextProjectId() external view returns (uint64); + + function nextPoolId() external view returns (uint64); + + function owner() external view returns (address); + + function xcmOracleAddress() external view returns (address); +} diff --git a/src/interfaces/IXCMOracle.sol b/src/interfaces/IXCMOracle.sol new file mode 100644 index 0000000..bc43aeb --- /dev/null +++ b/src/interfaces/IXCMOracle.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.26; + +interface IXCMOracle { + struct PoolInfo { + uint256 assetAmount; + uint256 vAssetAmount; + } + struct RateInfo { + uint8 mintRate; + uint8 redeemRate; + } + + function getCurrencyIdByAssetAddress( + address _assetAddress + ) external view returns (bytes2); + + function tokenPool( + bytes2 _currencyId + ) external view returns (PoolInfo memory); + + function rateInfo() external view returns (RateInfo memory); + + // _assetAddress: Asset address, e.g. DOT, KSM + // _assetAmount: Input asset amount, get vAsset amount + // _vAssetAmount: Input vAsset amount, get asset amount + function getVTokenByToken( + address _assetAddress, + uint256 _assetAmount + ) external view returns (uint256); + + function getTokenByVToken( + address _assetAddress, + uint256 _vAssetAmount + ) external view returns (uint256); +} diff --git a/src/mocks/MockERC20.sol b/src/mocks/MockERC20.sol new file mode 100644 index 0000000..7def70d --- /dev/null +++ b/src/mocks/MockERC20.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +/* solhint-disable */ +pragma solidity ^0.8.24; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockERC20 is ERC20 { + uint8 internal customDecimals; + + constructor(string memory name, string memory symbol) ERC20(name, symbol) { + _mint(msg.sender, 1e20 * (10 ** decimals())); + } + + function freeMint(uint256 amount) public { + _mint(msg.sender, amount); + } + + function freeMintTo(address to, uint256 amount) public { + _mint(to, amount); + } + + function setDecimals(uint8 _decimals) public { + customDecimals = _decimals; + } + + function decimals() public view override returns (uint8) { + return (customDecimals == 0) ? super.decimals() : customDecimals; + } +} +/* solhint-enable */ diff --git a/src/mocks/MockLaunchpool.sol b/src/mocks/MockLaunchpool.sol new file mode 100644 index 0000000..b518e83 --- /dev/null +++ b/src/mocks/MockLaunchpool.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +/* solhint-disable */ + +pragma solidity ^0.8.26; + +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { DeployMockXCMOracle } from "../..//test/testutils/DeployMockXCMOracle.sol"; + +contract MockLaunchpool is Launchpool { + constructor( + address _projectOwner, + address _projectToken, + address _acceptedVAsset, + address _acceptedNativeAsset, + uint128 _startBlock, + uint128 _endBlock, + uint256 _maxVAssetPerStaker, + uint128[] memory _changeBlocks, + uint256[] memory _emissionRateChanges + ) + // Get hard-coded XCMOracle address for local testing + Launchpool( + 0xEF81930Aa8ed07C17948B2E26b7bfAF20144eF2a, + _projectOwner, + _projectToken, + _acceptedVAsset, + _acceptedNativeAsset, + _startBlock, + _endBlock, + _maxVAssetPerStaker, + _changeBlocks, + _emissionRateChanges + ) + {} + + // Wildcard setters for testing (beware when testing) + function wild_setTickBlock(uint128 _tickBlock) external { + tickBlock = _tickBlock; + } + + function wild_setLastNativeExRate(uint256 _lastNativeExRate) external { + lastNativeExRate = _lastNativeExRate; + } + + function wild_setAvgNativeExRateGradient( + uint256 _avgNativeExRateGradient + ) external { + avgNativeExRateGradient = _avgNativeExRateGradient; + } + + function wild_setNativeExRateSampleCount( + uint128 _nativeExRateSampleCount + ) external { + nativeExRateSampleCount = _nativeExRateSampleCount; + } + + function wild_updateNativeTokenExchangeRate( + uint256 _nativeAmount, + uint256 _vTokenAmount + ) external { + _updateNativeTokenExchangeRate(_nativeAmount, _vTokenAmount); + } + + function wild_setLastNativeExRateUpdateBlock( + uint128 _lastNativeExRateUpdateBlock + ) external { + lastNativeExRateUpdateBlock = _lastNativeExRateUpdateBlock; + } + + function wild_setPlatformAdminAddress( + address _platformAdminAddress + ) external { + platformAdminAddress = _platformAdminAddress; + } + + function wild_setOwnerShareOfInterest( + uint128 _ownerShareOfInterest + ) external { + ownerShareOfInterest = _ownerShareOfInterest; + } + + // Expose internal methods for testing + function exposed_getVTokenByTokenWithoutFee( + uint256 _nativeAmount + ) public view returns (uint256) { + return _getVTokenByTokenWithoutFee(_nativeAmount); + } + + function exposed_getTokenByVTokenWithoutFee( + uint256 _vTokenAmount + ) public view returns (uint256) { + return _getTokenByVTokenWithoutFee(_vTokenAmount); + } + + function exposed_getEstimatedNativeExRateAtEnd() + public + view + returns (uint256) + { + return _getEstimatedNativeExRateAtEnd(); + } + + function exposed_getTokenDecimals( + address _tokenAddress + ) public view returns (uint8) { + return _getTokenDecimals(_tokenAddress); + } + + function exposed_getActiveBlockDelta( + uint256 from, + uint256 to + ) public view returns (uint256) { + return _getActiveBlockDelta(from, to); + } + + function exposed_getPlatformAndOwnerClaimableVAssets() + public + view + returns (uint256 ownerClaims, uint256 platformFee) + { + (ownerClaims, platformFee) = _getPlatformAndOwnerClaimableVAssets(); + } + + function exposed_getPendingExchangeRate() public view returns (uint256) { + return _getPendingExchangeRate(); + } + + function exposed_getClaimableProjectToken() public view returns (uint256) { + return exposed_getClaimableProjectToken(); + } + + // function _getVTokenByTokenWithoutFee( + // uint256 _nativeAmount + // ) internal view override returns (uint256 vAssetAmount) { + // return + // // Temporary solution + // xcmOracle.getVTokenByToken( + // address(acceptedNativeAsset), + // _nativeAmount + // ); + // } + + // function _getTokenByVTokenWithoutFee( + // uint256 _vAssetAmount + // ) internal view override returns (uint256 nativeAmount) { + // // Temporary solution + // return + // xcmOracle.getTokenByVToken( + // address(acceptedNativeAsset), + // _vAssetAmount + // ); + // } + + // function _preInit() internal override { + // // Set platform admin address for testing + // platformAdminAddress = address(0x868); + // xcmOracle = IXCMOracle(0xEF81930Aa8ed07C17948B2E26b7bfAF20144eF2a); + // } +} +/* solhint-enable */ diff --git a/src/mocks/MockXCMOracle.sol b/src/mocks/MockXCMOracle.sol new file mode 100644 index 0000000..6fa2788 --- /dev/null +++ b/src/mocks/MockXCMOracle.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT +/* solhint-disable */ +pragma solidity ^0.8.26; +import "forge-std/Test.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IERC20Decimal { + function decimals() external view returns (uint8); +} + +contract MockXCMOracle { + struct PoolInfo { + uint256 nativeAmount; + uint256 vAssetAmount; + } + + PoolInfo public poolInfo = PoolInfo(1 ether, 1 ether); + + uint256 public blockInterval; + uint256 public lastUpdatedBlock; + uint256 public nativeIncrementPerInterval; + + uint256 public immutable NETWORK_BLOCK_TIME; + uint256 public constant APY_DECIMALS = 6; + uint256 public constant RATE_DECIMALS = 18; + + /** + * + * @param _initialRate initial exchange rate, 18-decimal precision, e.g. 1.2 => 1.2e18, 1.5524 => 1.5524e18 + * @param _blockInterval block interval for exchange rate update (how many blocks in an interval) + * @param _apy APY in percentage, 6-decimal precision, e.g. 0.01 => 10.000, 0.5034 => 503.400 + * @param _networkBlockTime block time in seconds, e.g 12 secs for Ethereum, 6 secs for Moonbeam + */ + constructor( + uint256 _initialRate, + uint256 _blockInterval, + uint256 _apy, + uint256 _networkBlockTime + ) { + if (_networkBlockTime == 0) { + revert( + "Dawg, u tryna pull a division-by-0 stunt? _networkBlockTime must be ge. 1" + ); + } + + if (_blockInterval == 0) { + revert( + "Dawg, u tryna pull a division-by-0 stunt? _blockInterval must be ge. 1" + ); + } + + blockInterval = _blockInterval; + NETWORK_BLOCK_TIME = _networkBlockTime; + + setExchangeRate(_initialRate); + setAPY(_apy); + } + + /** + * + * @notice Set native increment per interval (a more direct alternative to setAPY) + * @param _nativeIncrementPerInterval native increment per interval + */ + function setNativeIncrementPerInterval( + uint256 _nativeIncrementPerInterval + ) public { + nativeIncrementPerInterval = _nativeIncrementPerInterval; + lastUpdatedBlock = block.number; + } + + /** + * + * @notice Set APY for the oracle, which will be used to derive native increment per interval + * @param _apy APY in percentage, 6-decimal precision, e.g. 0.01 => 10.000, 0.5034 => 503.400 + * @param _apy will be used to derive native increment per interval + */ + function setAPY(uint256 _apy) public { + // Derive native increment amount from APY + uint256 annualNativeIncrement = (_apy * poolInfo.nativeAmount) / + (10 ** APY_DECIMALS); + uint256 nativeIncrementPerBlock = annualNativeIncrement / + (365 days / NETWORK_BLOCK_TIME); + setNativeIncrementPerInterval(nativeIncrementPerBlock * blockInterval); + } + + /** + * + * @notice Set custom exchange rate for the oracle + * @param _exchangeRate exchange rate to set + */ + function setExchangeRate(uint256 _exchangeRate) public { + poolInfo.nativeAmount = + (poolInfo.vAssetAmount * _exchangeRate) / + (10 ** RATE_DECIMALS); + lastUpdatedBlock = block.number; + } + + /** + * + * @notice Decide the number of blocks per interval for exchange rate update + * @param _blockInterval block interval for exchange rate update (how many blocks in an interval) + */ + function setBlockInterval(uint256 _blockInterval) public { + lastUpdatedBlock = block.number; + blockInterval = _blockInterval; + } + + /** + * + * @notice Re-estimate exchange rate based on the current block number + */ + function syncExchangeRate() public { + uint256 newestRate = getCurrentExchangeRate(); + setExchangeRate(newestRate); + } + + function getCurrentExchangeRate() public view returns (uint256) { + uint256 blocksPassed = block.number - lastUpdatedBlock; + uint256 intervals = blocksPassed / blockInterval; + uint256 currentNativeAmt = poolInfo.nativeAmount + + (intervals * nativeIncrementPerInterval); + return + (currentNativeAmt * (10 ** RATE_DECIMALS)) / poolInfo.vAssetAmount; + } + + function getLastSetExchangeRate() public view returns (uint256) { + console.log("Last set native amount: %d", poolInfo.nativeAmount); + return + (poolInfo.nativeAmount * (10 ** RATE_DECIMALS)) / + poolInfo.vAssetAmount; + } + + /** + * + * @notice Mock return same token pool for all currency + * @param _currencyId Currency ID + */ + function tokenPool( + bytes2 _currencyId + ) public view returns (PoolInfo memory) { + return poolInfo; + // TODO: Implement dynamic exchange rate here: + } + + /** + * + * @notice Mock return same token pool for all native address + * @param _nativeAddress native asset address + */ + function getCurrencyIdByAssetAddress( + address _nativeAddress + ) public view returns (bytes2) { + return 0x0806; + } + + /** + * @notice No more needed, we raw-dogging conversionss + * between vAsset and native in Launchpool.sol + * + **/ + // function getVTokenByToken( + // address _assetAddress, + // uint256 amount + // ) public view returns (uint256) { + // return amount / getCurrentExchangeRate(); + // } + + // function getTokenByVToken( + // address _assetAddress, + // uint256 amount + // ) public view returns (uint256) { + // return amount * getCurrentExchangeRate(); + // } +} +/* solhint-enable*/ diff --git a/src/non-upgradeable/Launchpool.sol b/src/non-upgradeable/Launchpool.sol new file mode 100644 index 0000000..f843102 --- /dev/null +++ b/src/non-upgradeable/Launchpool.sol @@ -0,0 +1,807 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +// import { console } from "forge-std/console.sol"; // remove when deploy + +// import { console } from "forge-std/console.sol"; // remove when deploy + +contract Launchpool is Ownable, ReentrancyGuard, Pausable { + using SafeERC20 for IERC20; + + struct Staker { + uint256 nativeAmount; + uint256 claimOffset; + } + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////////// CONTRACT STATES /////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + uint256 public cumulativeExchangeRate; + uint128 public startBlock; + uint128 public endBlock; + uint128 public tickBlock; + uint128 public ownerShareOfInterest = 90; // 90% of the interest goes to the PO, the rest is platform fee + uint256 public maxTokenPerStaker; + uint256 public maxStakers; + uint256 public totalNativeStake; + + uint256 public immutable SCALING_FACTOR; + uint256 public constant MAX_DECIMALS = 30; + uint256 public constant BASE_PRECISION = 1e30; + uint256 public lastProcessedChangeBlockIndex; + + address public platformAdminAddress = + 0xfD48761638E3a8C368ABAEFa9859cf6baa6C3c27; + + mapping(uint128 => uint256) public emissionRateChanges; + uint128[] public changeBlocks; + + IERC20 public projectToken; + IERC20 public acceptedVAsset; + IERC20 public acceptedNativeAsset; //For XCMOracle cal + IXCMOracle public xcmOracle; + + mapping(address => Staker) public stakers; + + // Last-recorded exchange rate between acceptedNativeAsset and acceptedVAsset + uint256 public lastNativeExRate; + // The numerator to calculate the weighted average gradient of the exchange rate (e.g. 100/block) + uint256 public avgNativeExRateGradient; + + // Sample count + uint128 public nativeExRateSampleCount; + uint128 public lastNativeExRateUpdateBlock; + + uint256 public immutable ONE_VTOKEN; + + // TODO: add test for this + bool public platformFeeClaimed; + + /////////////////////////////////////////////////////////////////////////////// + /////////////////////////////// CONTRACT EVENTS ////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + event Staked(address indexed user, uint256 amount); + event Unstaked(address indexed user, uint256 amount); + + ///////////////////////////////////////////////////////////////////////////// + //////////////////////// VALIDATE POOL INFO ERRORS ///////////////////////// + /////////////////////////////////////////////////////////////////////////// + error StartBlockMustBeInFuture(); + error EndBlockMustBeAfterstartBlock(); + error ZeroAddress(); + error FirstChangeBlockMustBeStartBlock(); + error TotalProjectTokensMustBeGreaterThanZero(); + error MaxAndMinTokensPerStakerMustBeGreaterThanZero(); + error ArraysLengthMismatch(); + error NoEmissionRateChangesProvided(); + error DecimalsTooHigh(address tokenAddress); // 30 is the max + error FailedToReadTokenDecimals(); // if decimals can't be fetched + + ///////////////////////////////////////////////////////////////////////////// + //////////////////////// OTHER ERRORS ////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + error ProjectTokenNotRecoverable(); + error MustBeAfterPoolEnd(); + error NotPlatformAdmin(); + error ZeroAmountNotAllowed(); + error ExceedMaxTokensPerStaker(); + error ExceedWithdrawableVTokens(); + error ExceedNativeStake(); + error MustBeDuringPoolTime(); + error PlatformFeeAlreadyClaimed(); + + /////////////////////////////////////////////////////////////////////////// + //////////////////////////////// MODIFIERS /////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + modifier validTokenAddress(address _tokenAdrees) { + if (_tokenAdrees == address(0)) { + revert ZeroAddress(); + } + _; + } + + modifier validStakingRange(uint256 _maxTokenPerStaker) { + if (_maxTokenPerStaker == 0) + revert MaxAndMinTokensPerStakerMustBeGreaterThanZero(); + _; + } + + modifier notProjectToken(address _tokenAddress) { + if (_tokenAddress == address(projectToken)) { + revert ProjectTokenNotRecoverable(); + } + _; + } + + modifier afterPoolEnd() { + // TODO: re-validate this (just updated from < to <=) + if (block.number <= endBlock) { + revert MustBeAfterPoolEnd(); + } + _; + } + + modifier poolIsActive() { + if (block.number < startBlock || block.number > endBlock) { + revert MustBeDuringPoolTime(); + } + _; + } + + modifier onlyPlatformAdmin() { + if (msg.sender != platformAdminAddress) { + revert NotPlatformAdmin(); + } + _; + } + + modifier nonZeroAmount(uint256 _amount) { + if (_amount == 0) { + revert ZeroAmountNotAllowed(); + } + _; + } + + modifier handleNativeExRateAfterEnd() { + // Enforce update of avg. native exrate gradient if it's 0 after end + if (avgNativeExRateGradient == 0 && block.number > endBlock) { + uint256 nativePerVToken = _getTokenByVTokenWithoutFee(ONE_VTOKEN); + _updateNativeTokenExchangeRate(nativePerVToken, ONE_VTOKEN); + } + _; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////// CONSTRUCTOR ////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + constructor( + address xcmOracleAddress, + address _projectOwner, + address _projectToken, + address _acceptedVAsset, + address _acceptedNativeAsset, + uint128 _startBlock, + uint128 _endBlock, + uint256 _maxTokenPerStaker, + uint128[] memory _changeBlocks, + uint256[] memory _emissionRateChanges + ) + Ownable(_projectOwner) + validTokenAddress(_projectToken) + validTokenAddress(_acceptedVAsset) + validTokenAddress(_acceptedNativeAsset) + validStakingRange(_maxTokenPerStaker) + { + _preInit(); + xcmOracle = IXCMOracle(xcmOracleAddress); + + uint256 currentBlock = block.number; + if (_startBlock <= currentBlock) revert StartBlockMustBeInFuture(); + if (_endBlock <= _startBlock) revert EndBlockMustBeAfterstartBlock(); + + // Ensure the first change block matches the start block + uint256 changeBlocksLen = _changeBlocks.length; + if (changeBlocksLen <= 0) { + revert NoEmissionRateChangesProvided(); + } + + // Consider adding this in Launchpool constructor + // for (uint256 i = 1; i < changeBlocksLen; i++) { + // if (_changeBlocks[i] <= _changeBlocks[i - 1]) { + // revert ChangeBlocksNotInAscendingOrder(); + // } + // } + + if (_changeBlocks[0] != _startBlock) { + revert FirstChangeBlockMustBeStartBlock(); + } + + if (_emissionRateChanges.length != changeBlocksLen) { + revert ArraysLengthMismatch(); + } + + uint8 pTokenDecimals = _getTokenDecimals(address(_projectToken)); + uint8 vAssetDecimals = _getTokenDecimals(address(_acceptedVAsset)); + + SCALING_FACTOR = BASE_PRECISION / (10 ** pTokenDecimals); + ONE_VTOKEN = 10 ** vAssetDecimals; + + unchecked { + for (uint256 i = 0; i < changeBlocksLen; ++i) { + emissionRateChanges[_changeBlocks[i]] = _emissionRateChanges[i]; + } + } + + // Record native exchange rate at start block + lastNativeExRate = _getTokenByVTokenWithoutFee(ONE_VTOKEN); + ++nativeExRateSampleCount; + lastNativeExRateUpdateBlock = uint128(currentBlock); + + changeBlocks = _changeBlocks; + projectToken = IERC20(_projectToken); + acceptedVAsset = IERC20(_acceptedVAsset); + acceptedNativeAsset = IERC20(_acceptedNativeAsset); + startBlock = _startBlock; + endBlock = _endBlock; + maxTokenPerStaker = _maxTokenPerStaker; + tickBlock = _startBlock; + } + + /////////////////////////////////////////////////////////////////////////// + //////////////////////////////// FUNCTION //////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + function pause() external onlyPlatformAdmin { + _pause(); + } + + function unpause() external onlyPlatformAdmin { + _unpause(); + } + + function stake( + uint256 _vTokenAmount + ) + external + nonZeroAmount(_vTokenAmount) + poolIsActive + whenNotPaused + nonReentrant + { + Staker storage investor = stakers[msg.sender]; + uint256 nativeAmount = _getTokenByVTokenWithoutFee(_vTokenAmount); + + if (investor.nativeAmount == 0) { + if (nativeAmount > maxTokenPerStaker) { + revert ExceedMaxTokensPerStaker(); + } + } else if (investor.nativeAmount + nativeAmount > maxTokenPerStaker) { + revert ExceedMaxTokensPerStaker(); + } + + _updateNativeTokenExchangeRate(nativeAmount, _vTokenAmount); + + _tick(); + + if (investor.nativeAmount > 0) { + uint256 claimableProjectTokenAmount = (investor.nativeAmount * + cumulativeExchangeRate) / + SCALING_FACTOR - + investor.claimOffset; + + if (claimableProjectTokenAmount > 0) { + projectToken.safeTransfer( + address(msg.sender), + claimableProjectTokenAmount + ); + } + } + + investor.nativeAmount += nativeAmount; + totalNativeStake += nativeAmount; + + acceptedVAsset.safeTransferFrom( + address(msg.sender), + address(this), + _vTokenAmount + ); + + investor.claimOffset = + (investor.nativeAmount * cumulativeExchangeRate) / + SCALING_FACTOR; + + emit Staked(address(msg.sender), _vTokenAmount); + } + + function unstake( + uint256 _vTokenAmount + ) + external + nonZeroAmount(_vTokenAmount) + whenNotPaused + nonReentrant + handleNativeExRateAfterEnd + { + address stakerAddr = _msgSender(); + Staker memory staker = stakers[stakerAddr]; + uint256 withdrawnNativeTokens = _handleUnstakeAmount( + staker, + _vTokenAmount + ); + + _updateNativeTokenExchangeRate(staker.nativeAmount, _vTokenAmount); + _tick(); + + // Handle distribution of project tokens + uint256 cumExRate = cumulativeExchangeRate; + uint256 claimableProjectTokenAmount = ((staker.nativeAmount * + cumExRate) / SCALING_FACTOR) - staker.claimOffset; + + if (claimableProjectTokenAmount > 0) { + projectToken.safeTransfer( + address(msg.sender), + claimableProjectTokenAmount + ); + } + + uint256 remainingAmount = staker.nativeAmount - withdrawnNativeTokens; + staker.claimOffset = (remainingAmount * cumExRate) / SCALING_FACTOR; + staker.nativeAmount = remainingAmount; + totalNativeStake -= withdrawnNativeTokens; + + // Write investor back to storage + stakers[stakerAddr] = staker; + + emit Unstaked(stakerAddr, _vTokenAmount); + + acceptedVAsset.safeTransfer(stakerAddr, _vTokenAmount); + } + + // Need modification + /** + * @notice Emergency withdrawal function that works even when contract is paused + * @dev Users forfeit any earned project tokens when using this function + * @param _withdrawnVTokens Amount of vTokens to withdraw + */ + function unstakeWithoutProjectToken( + uint256 _withdrawnVTokens + ) external nonZeroAmount(_withdrawnVTokens) nonReentrant { + address stakerAddr = _msgSender(); + Staker memory staker = stakers[stakerAddr]; + uint256 withdrawnNativeTokens = _handleUnstakeAmount( + staker, + _withdrawnVTokens + ); + + _updateNativeTokenExchangeRate(staker.nativeAmount, _withdrawnVTokens); + _tick(); + + staker.nativeAmount -= withdrawnNativeTokens; + staker.claimOffset = + (staker.nativeAmount * cumulativeExchangeRate) / + SCALING_FACTOR; + totalNativeStake -= withdrawnNativeTokens; + + // Write staker back to storage + stakers[stakerAddr] = staker; + + emit Unstaked(address(msg.sender), _withdrawnVTokens); + + acceptedVAsset.safeTransfer(address(msg.sender), _withdrawnVTokens); + } + + function recoverWrongToken( + address _tokenAddress + ) external onlyOwner notProjectToken(_tokenAddress) { + IERC20 token = IERC20(_tokenAddress); + uint256 balance = token.balanceOf(address(this)); + token.safeTransfer(owner(), balance); + } + + // TODO: need to fix this (cannot claim before all users had claimed) + function claimLeftoverProjectToken() external onlyOwner afterPoolEnd { + uint256 balance = projectToken.balanceOf(address(this)); + projectToken.safeTransfer(address(msg.sender), balance); + projectToken.safeTransfer(owner(), balance); + } + + // TODO: add test for this + function claimOwnerInterest() + external + onlyOwner + nonReentrant + handleNativeExRateAfterEnd + { + ( + uint256 ownerClaims, + uint256 platformFee + ) = _getPlatformAndOwnerClaimableVAssets(); + acceptedVAsset.safeTransfer(owner(), ownerClaims); + acceptedVAsset.safeTransfer(platformAdminAddress, platformFee); + } + + function claimPlatformFee() + external + onlyPlatformAdmin + afterPoolEnd + nonReentrant + handleNativeExRateAfterEnd + { + if (platformFeeClaimed) { + revert PlatformFeeAlreadyClaimed(); + } + + platformFeeClaimed = true; + + // Enforce update of avg. native exrate gradient if it's 0 + // if (avgNativeExRateGradient == 0) { + // uint256 vAssetAmount = ONE_VTOKEN; + // uint256 nativeAmount = _getTokenByVTokenWithoutFee(vAssetAmount); + // _updateNativeTokenExchangeRate(nativeAmount, vAssetAmount); + // } + (, uint256 platformFee) = _getPlatformAndOwnerClaimableVAssets(); + acceptedVAsset.safeTransfer(platformAdminAddress, platformFee); + } + + function setXCMOracleAddress( + address _xcmOracleAddress + ) external onlyPlatformAdmin { + xcmOracle = IXCMOracle(_xcmOracleAddress); + } + + function getPoolInfo() + external + view + returns (uint128, uint128, uint256, uint256) + { + return ( + startBlock, + endBlock, + getTotalProjectToken(), + getEmissionRate() + ); + } + + function getWithdrawableVTokens( + uint256 _withdrawnNativeTokens + ) public view returns (uint256 withdrawableVAssets) { + if (block.number <= endBlock) { + withdrawableVAssets = _getVTokenByTokenWithoutFee( + _withdrawnNativeTokens + ); + } else { + uint256 exRateAtEnd = _getEstimatedNativeExRateAtEnd(); + withdrawableVAssets = + (_withdrawnNativeTokens * ONE_VTOKEN) / + exRateAtEnd; + } + + uint256 stakedVTokens = getTotalStakedVTokens(); + if (withdrawableVAssets > stakedVTokens) { + withdrawableVAssets = stakedVTokens; + } + } + + function getTotalStakedVTokens() public view returns (uint256) { + return acceptedVAsset.balanceOf(address(this)); + } + + function getTotalProjectToken() public view returns (uint256) { + return projectToken.balanceOf(address(this)); + } + + /** + * TODO: Need review + */ + function getStakingRange() public view returns (uint256, uint256) { + return (maxTokenPerStaker, maxStakers); + } + + function getEmissionRate() public view returns (uint256) { + /** + * TODO: should make this into a modifier for launchpool end scenario + */ + if (block.number >= endBlock) { + return 0; + } + + uint256 currentBlock = block.number; + uint256 emissionRate = 0; + uint256 len = changeBlocks.length; + for (uint256 i = lastProcessedChangeBlockIndex; i < len; ++i) { + if (currentBlock < changeBlocks[i]) { + break; + } + emissionRate = emissionRateChanges[changeBlocks[i]]; + } + return emissionRate; + } + + function getClaimableProjectToken( + address _investor + ) public view returns (uint256) { + Staker memory investor = stakers[_investor]; + + if (investor.nativeAmount == 0) { + return 0; + } + + return + (investor.nativeAmount * + (cumulativeExchangeRate + _getPendingExchangeRate())) / + SCALING_FACTOR - + investor.claimOffset; + } + + function getStakerNativeAmount( + address _investor + ) public view returns (uint256) { + return stakers[_investor].nativeAmount; + } + + /** + * @notice For setting variables, injecting mock dependencies pre-constructor run, etc. + * @dev Plz override this + */ + function _preInit() internal virtual {} + + function _handleUnstakeAmount( + Staker memory staker, + uint256 _withdrawnVTokens + ) internal returns (uint256 withdrawnNativeTokens) { + // Keep this as fail-fast mechanism to save gas + if (staker.nativeAmount == 0) { + revert ZeroAmountNotAllowed(); + } + + // Handle edge case: when the avg gradient is 0 after pool end + // TODO: add test for this + if (block.number > endBlock) { + if (avgNativeExRateGradient == 0) { + withdrawnNativeTokens = _getTokenByVTokenWithoutFee( + _withdrawnVTokens + ); + _updateNativeTokenExchangeRate( + withdrawnNativeTokens, + _withdrawnVTokens + ); + } else { + uint256 nativePerVToken = _getEstimatedNativeExRateAtEnd(); + withdrawnNativeTokens = + (_withdrawnVTokens * nativePerVToken) / + ONE_VTOKEN; + } + } else { + withdrawnNativeTokens = _getTokenByVTokenWithoutFee( + _withdrawnVTokens + ); + } + + uint256 withdrawableVTokens = getWithdrawableVTokens( + staker.nativeAmount + ); + + if (withdrawableVTokens < _withdrawnVTokens) { + revert ExceedWithdrawableVTokens(); + } + + if (staker.nativeAmount < withdrawnNativeTokens) { + revert ExceedNativeStake(); + } + + return (withdrawnNativeTokens); + } + + function _tick() internal { + uint256 currentBlock = block.number; + if (currentBlock == tickBlock) { + return; + } + + if (totalNativeStake == 0) { + unchecked { + tickBlock = uint128(block.number); + } + _updateLastProcessedIndex(); + return; + } + + cumulativeExchangeRate += _getPendingExchangeRate(); + tickBlock = uint128(currentBlock); + + _updateLastProcessedIndex(); + } + + function _updateLastProcessedIndex() internal { + uint256 len = changeBlocks.length; + for (uint256 i = lastProcessedChangeBlockIndex; i < len; i++) { + if (changeBlocks[i] > tickBlock) { + break; + } + lastProcessedChangeBlockIndex = i; + } + } + + // TODO: need testing and validation + function _updateNativeTokenExchangeRate( + uint256 _nativeAmount, + uint256 _vTokenAmount + ) internal { + uint256 currentBlock = block.number; + uint256 blockDelta = currentBlock - lastNativeExRateUpdateBlock; + + // Edge case: when multiple stakers stake at same block + if (blockDelta == 0) { + return; + } + + // Edge case: after the pool ends, if the avg gradient is larger than zero, we stop here, else let it be updated + // TODO: Add extensive invarianet tests for this edge case + bool isAfterEndBlock = currentBlock > endBlock; + bool isAvgGradientPositive = avgNativeExRateGradient > 0; + if (isAfterEndBlock && isAvgGradientPositive) { + return; + } + + // Edge case: prevent case when the time gap between 2 stakers is too small, the rate delta is 0 + uint256 newNativeExRate = (_nativeAmount * ONE_VTOKEN) / _vTokenAmount; + if (newNativeExRate <= lastNativeExRate) { + return; + } + + uint256 exRateDelta = newNativeExRate - lastNativeExRate; + uint256 newGradientSample = exRateDelta / blockDelta; + + // Only update the last native exchange rate states if before end block + if (!isAfterEndBlock) { + lastNativeExRate = newNativeExRate; + lastNativeExRateUpdateBlock = uint128(currentBlock); + } + + // Calculate rolling average of the gradient + avgNativeExRateGradient = + (avgNativeExRateGradient * + (nativeExRateSampleCount - 1) + + newGradientSample) / + (nativeExRateSampleCount); + + ++nativeExRateSampleCount; + } + + function _getPendingExchangeRate() internal view returns (uint256) { + if (totalNativeStake == 0) { + return 0; + } + + uint256 currentBlock = block.number; + uint128 periodStartBlock = tickBlock; + uint128 periodEndBlock; + uint256 len = changeBlocks.length; + uint256 accumulatedIncrease = 0; + uint256 i = lastProcessedChangeBlockIndex; + + for (; i < len; i++) { + periodEndBlock = changeBlocks[i]; + + if (periodEndBlock >= currentBlock) { + break; + } + + if (periodEndBlock <= periodStartBlock) { + continue; + } + + uint256 tickBlockDelta = _getActiveBlockDelta( + periodStartBlock, + periodEndBlock + ); + + uint256 emissionRate = emissionRateChanges[ + i == 0 ? changeBlocks[0] : changeBlocks[i - 1] + ]; + + accumulatedIncrease += + (emissionRate * tickBlockDelta * SCALING_FACTOR) / + totalNativeStake; + + periodStartBlock = periodEndBlock; + } + + uint256 finalDelta = _getActiveBlockDelta( + periodStartBlock, + currentBlock + ); + uint256 finalEmissionRate = (periodEndBlock <= currentBlock) + ? emissionRateChanges[periodEndBlock] // Get rate for the period that started at periodEndBlock + : emissionRateChanges[changeBlocks[i - 1]]; // Get rate after the last processed change block + + accumulatedIncrease += + (finalEmissionRate * finalDelta * SCALING_FACTOR) / + totalNativeStake; + + return accumulatedIncrease; + } + + /** + * @notice + * @dev This function should only be called after the pool end block, otherwise, + * there's risk of block.number - lastNativeExRateUpdateBlock = 0 + */ + function _getEstimatedNativeExRateAtEnd() + internal + view + returns (uint256 estimatedNativeExRateAtEnd) + { + uint256 blocksTilEnd = endBlock - lastNativeExRateUpdateBlock; + // Handle edge case: when the gradient is 0 after pool end + if (block.number > endBlock && avgNativeExRateGradient == 0) { + uint256 newRate = _getTokenByVTokenWithoutFee(ONE_VTOKEN); + // TODO: add test for this (it must not and cannot be 0) + uint256 avgRateGradient = (newRate - lastNativeExRate) / + (block.number - lastNativeExRateUpdateBlock); + return + lastNativeExRate + + (avgRateGradient * (endBlock - lastNativeExRateUpdateBlock)); + } + + estimatedNativeExRateAtEnd = + lastNativeExRate + + (avgNativeExRateGradient * blocksTilEnd); + } + + function _getPlatformAndOwnerClaimableVAssets() + internal + view + returns (uint256 ownerClaims, uint256 platformFee) + { + uint256 allVAssets = acceptedVAsset.balanceOf(address(this)); + + if (allVAssets == 0) { + return (0, 0); + } + + uint256 investorVAssets = getWithdrawableVTokens(totalNativeStake); + uint256 combinedClaims = allVAssets - investorVAssets; + + if (platformFeeClaimed) { + return (combinedClaims, 0); + } + ownerClaims = (combinedClaims * ownerShareOfInterest) / 100; + platformFee = combinedClaims - ownerClaims; + } + + // TODO: add test for this + function _getVTokenByTokenWithoutFee( + uint256 _nativeAmount + ) internal view virtual returns (uint256 vAssetAmount) { + bytes2 currencyId = xcmOracle.getCurrencyIdByAssetAddress( + address(acceptedNativeAsset) + ); + IXCMOracle.PoolInfo memory poolInfo = xcmOracle.tokenPool(currencyId); + vAssetAmount = + (_nativeAmount * poolInfo.vAssetAmount) / + poolInfo.assetAmount; + } + + // TODO: add test for this + function _getTokenByVTokenWithoutFee( + uint256 _vAssetAmount + ) internal view virtual returns (uint256 nativeAmount) { + bytes2 currencyId = xcmOracle.getCurrencyIdByAssetAddress( + address(acceptedNativeAsset) + ); + IXCMOracle.PoolInfo memory poolInfo = xcmOracle.tokenPool(currencyId); + + nativeAmount = + (_vAssetAmount * poolInfo.assetAmount) / + poolInfo.vAssetAmount; + } + + function _getActiveBlockDelta( + uint256 from, + uint256 to + ) internal view returns (uint256) { + if (to <= endBlock) { + return to - from; + } else if (from >= endBlock) { + return 0; + } + return endBlock - from; + } + + function _getTokenDecimals( + address _tokenAddress + ) internal view returns (uint8) { + try IERC20Metadata(_tokenAddress).decimals() returns (uint8 dec) { + return dec; + } catch { + revert FailedToReadTokenDecimals(); + } + } +} diff --git a/src/upgradeable/v1/ProjectHubUpgradeable.sol b/src/upgradeable/v1/ProjectHubUpgradeable.sol new file mode 100644 index 0000000..583e31b --- /dev/null +++ b/src/upgradeable/v1/ProjectHubUpgradeable.sol @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { SelfMultiCall } from "@src/utils/SelfMultiCall.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +library PoolTypeLib { + enum PoolType { + LAUNCHPOOL, + LAUNCHPAD, + VESTING, + FARMING + } +} + +/** + * @title ProjectLibrary + * @dev Library containing project management logic for ProjectHubUpgradeable + */ +library ProjectLibrary { + struct Project { + uint64 projectId; + address projectOwner; + // Always add new fields at the end + } + + // Events + event ProjectCreated( + uint64 indexed projectId, + address indexed projectOwner + ); + + // Errors + error ProjectNotFound(); + error NotProjectOwner(); + + /** + * @dev Creates a new project and assigns ownership to the caller + * @param projects Mapping of projects + * @param nextProjectId Current project ID counter + * @param sender Address of the caller + * @return projectId The ID of the newly created project + * @return newNextProjectId The updated project ID counter + */ + function createProject( + mapping(uint64 => Project) storage projects, + uint64 nextProjectId, + address sender + ) external returns (uint64 projectId, uint64 newNextProjectId) { + projectId = nextProjectId; + projects[projectId] = Project(projectId, sender); + emit ProjectCreated(projectId, sender); + unchecked { + newNextProjectId = nextProjectId + 1; + } + } + + /** + * @dev Validates if a project exists + * @param projects Mapping of projects + * @param projectId The project ID to validate + */ + function validateProjectExists( + mapping(uint64 => Project) storage projects, + uint64 projectId + ) public view { + if (projects[projectId].projectId == 0) { + revert ProjectNotFound(); + } + } + + /** + * @dev Validates if the caller is the owner of a project + * @param projects Mapping of projects + * @param projectId The project ID to validate + * @param sender Address of the caller + */ + function validateProjectOwner( + mapping(uint64 => Project) storage projects, + uint64 projectId, + address sender + ) public view { + validateProjectExists(projects, projectId); + if (projects[projectId].projectOwner != sender) { + revert NotProjectOwner(); + } + } +} + +/** + * @title PoolLibrary + * @dev Library containing pool management logic for ProjectHubUpgradeable + */ +library LaunchpoolLibrary { + struct Pool { + uint64 poolId; + PoolTypeLib.PoolType poolType; + address poolAddress; + uint64 projectId; + } + + struct LaunchpoolCreationParams { + uint64 projectId; + uint256 projectTokenAmount; + address projectToken; + address vAsset; + uint128 startBlock; + uint128 endBlock; + uint256 maxVTokensPerStaker; + uint128[] changeBlocks; + uint256[] emissionRateChanges; + } + + // Events + event LaunchpoolCreated( + uint64 indexed projectId, + PoolTypeLib.PoolType indexed poolType, + uint64 poolId, + address projectToken, + address indexed vAsset, + address poolAddress, + uint128 startBlock, + uint128 endBlock + ); + + // Errors + error PoolNotFound(); + + /** + * @dev Creates a new launchpool + * @param pools Mapping of pools + * @param nextPoolId Current pool ID counter + * @param params Parameters for launchpool creation + * @param projectOwner Address of the caller + * @return poolId The ID of the newly created pool + * @return newNextPoolId The updated pool ID counter + * @return poolAddress The address of the created launchpool contract + */ + function createLaunchpool( + mapping(uint64 => Pool) storage pools, + uint64 nextPoolId, + address nativeAsset, + address xcmOracleAddress, + LaunchpoolCreationParams calldata params, + address projectOwner + ) + external + returns (uint64 poolId, uint64 newNextPoolId, address poolAddress) + { + // Create a new launchpool and new launchpool record + poolAddress = address( + new Launchpool( + xcmOracleAddress, + projectOwner, + params.projectToken, + params.vAsset, + nativeAsset, + params.startBlock, + params.endBlock, + params.maxVTokensPerStaker, + params.changeBlocks, + params.emissionRateChanges + ) + ); + + // Transfer project tokens from project owner to launchpool + // TODO: add tests for this + IERC20(params.projectToken).transferFrom( + projectOwner, + poolAddress, + params.projectTokenAmount + ); + + // Register pool in storage + poolId = nextPoolId; + pools[poolId] = Pool( + poolId, + PoolTypeLib.PoolType.LAUNCHPOOL, + poolAddress, + params.projectId + ); + + emit LaunchpoolCreated( + params.projectId, + PoolTypeLib.PoolType.LAUNCHPOOL, + poolId, + params.projectToken, + params.vAsset, + poolAddress, + params.startBlock, + params.endBlock + ); + + unchecked { + newNextPoolId = nextPoolId + 1; + } + } + + /** + * @dev Validates if a pool exists + * @param pools Mapping of pools + * @param poolId The pool ID to validate + */ + function validatePoolExists( + mapping(uint64 => Pool) storage pools, + uint64 poolId + ) public view { + if (pools[poolId].poolId == 0) { + revert PoolNotFound(); + } + } +} + +/** + * @title ProjectHubUpgradeable + * @dev Main contract for managing projects and pools on the Defrost platform + * This implementation uses libraries to reduce bytecode size + */ +contract ProjectHubUpgradeable is + Initializable, + OwnableUpgradeable, + SelfMultiCall +{ + // Using libraries + // using ProjectLibrary for mapping(uint64 => ProjectLibrary.Project); + // using LaunchpoolLibrary for mapping(uint64 => LaunchpoolLibrary.Pool); + using ProjectLibrary for *; + using LaunchpoolLibrary for *; + + // State variables + mapping(uint64 => ProjectLibrary.Project) public projects; + mapping(uint64 => LaunchpoolLibrary.Pool) public pools; + mapping(address => address) public vAssetToNativeAsset; + uint64 public nextProjectId; + uint64 public nextPoolId; + address public xcmOracleAddress; + + // Events + event VAssetMappingUpdated( + address indexed vAsset, + address indexed nativeAsset + ); + + // Custom Errors + error AddressZero(); + error TokensArraysLengthMismatch(); + error NotAcceptedVAsset(); + + modifier notZeroAddress(address _address) { + if (_address == address(0)) { + revert AddressZero(); + } + _; + } + + /** + * @dev Initializes the contract with owner and initial accepted vAssets + * @param _initialOwner Address of the initial contract owner + * @param _initialVAssets Array of initially accepted vAsset addresses + */ + function initialize( + address _xcmOracleAddress, + address _initialOwner, + address[] calldata _initialVAssets, + address[] calldata _initialNativeAssets + ) external initializer { + __Ownable_init(_initialOwner); + + xcmOracleAddress = _xcmOracleAddress; + + uint256 vAssetCount = _initialVAssets.length; + if (vAssetCount != _initialNativeAssets.length) { + revert TokensArraysLengthMismatch(); + } + + for (uint256 i = 0; i < vAssetCount; ++i) { + vAssetToNativeAsset[_initialVAssets[i]] = _initialNativeAssets[i]; + } + + nextProjectId = 1; + nextPoolId = 1; + } + + /** + * @dev Creates a new project and assigns ownership to the caller + */ + function createProject() external { + (, uint64 newNextProjectId) = ProjectLibrary.createProject( + projects, + nextProjectId, + _msgSender() + ); + nextProjectId = newNextProjectId; + } + + /** + * @dev Creates a new launchpool + * @param _params Parameters for launchpool creation + * @return The ID of the newly created pool + */ + function createLaunchpool( + LaunchpoolLibrary.LaunchpoolCreationParams calldata _params + ) external returns (uint64) { + // Get native asset and verify vAsset is accepted + address nativeAsset = vAssetToNativeAsset[_params.vAsset]; + if (nativeAsset == address(0)) { + revert NotAcceptedVAsset(); + } + + address projectOwner = _msgSender(); + + // Verify caller is project owner + ProjectLibrary.validateProjectOwner( + projects, + _params.projectId, + projectOwner + ); + + (uint64 poolId, uint64 newNextPoolId, ) = LaunchpoolLibrary + .createLaunchpool( + pools, + nextPoolId, + nativeAsset, + xcmOracleAddress, + _params, + projectOwner + ); + + nextPoolId = newNextPoolId; + return poolId; + } + + /** + * @dev Sets whether a vAsset is accepted for pools + * @param _vAsset Address of the vAsset + * @param _nativeAsset Address of the native asset + */ + function setNativeAssetForVAsset( + address _vAsset, + address _nativeAsset + ) external notZeroAddress(_vAsset) notZeroAddress(_nativeAsset) onlyOwner { + vAssetToNativeAsset[_vAsset] = _nativeAsset; + + emit VAssetMappingUpdated(_vAsset, _nativeAsset); + } + + function removeVAssetSupport( + address _vAsset + ) external notZeroAddress(_vAsset) onlyOwner { + delete vAssetToNativeAsset[_vAsset]; + emit VAssetMappingUpdated(_vAsset, address(0)); + } + + function _msgSender() internal view override returns (address sender) { + sender = _getMultiCallSender(); + return sender != address(0) ? sender : super._msgSender(); + } +} diff --git a/src/utils/SelfMultiCall.sol b/src/utils/SelfMultiCall.sol new file mode 100644 index 0000000..894fafe --- /dev/null +++ b/src/utils/SelfMultiCall.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +contract SelfMultiCall { + bytes32 public constant MULTICALL_SENDER_SLOT = + keccak256("SelfMultiCall.ORIGINAL_SENDER_SLOT"); + + error MultiCallFailed( + uint256 callIndex, + bytes callPayload, + bytes errorPayload + ); + + /** + * @notice Executes multiple calls in a single transaction + * @param callPayloadBatch Array of encoded function calls + * @return allReturnData Array of return values + */ + function selfMultiCall( + bytes[] calldata callPayloadBatch + ) external returns (bytes[] memory allReturnData) { + uint256 len = callPayloadBatch.length; + if (len == 0) { + return new bytes[](0); + } + + allReturnData = new bytes[](len); + + _setMultiCallSender(msg.sender); + + for (uint256 i; i < len; ) { + (bool success, bytes memory returnData) = address(this).call( + callPayloadBatch[i] + ); + if (!success) { + _setMultiCallSender(address(0)); + revert MultiCallFailed(i, callPayloadBatch[i], returnData); + } + allReturnData[i] = returnData; + + unchecked { + ++i; + } + } + + _setMultiCallSender(address(0)); + return allReturnData; + } + + function _setMultiCallSender(address sender) internal { + bytes32 position = MULTICALL_SENDER_SLOT; + assembly { + sstore(position, sender) + } + } + + /** + * @notice Context-preserving version of msg.sender + * for use in selfMultiCall + */ + function _getMultiCallSender() internal view returns (address sender) { + bytes32 position = MULTICALL_SENDER_SLOT; + assembly { + sender := sload(position) + } + return sender; + } +} diff --git a/test/LaunchPoolFactory/CreatePool.t.sol b/test/LaunchPoolFactory/CreatePool.t.sol deleted file mode 100644 index 99bd83b..0000000 --- a/test/LaunchPoolFactory/CreatePool.t.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "forge-std/Test.sol"; -import { LaunchPoolFactory } from "../../src/LaunchPoolFactory.sol"; -import { LaunchPool } from "../../src/LaunchPool.sol"; - -import { StdCheats } from "forge-std/StdCheats.sol"; - -// @todo: Improve testcase later on when implementation for valid vAsset -contract CreateLaunchPoolTest is Test { - LaunchPoolFactory public poolFactory; - LaunchPool public launchPool; - - function setUp() public { - poolFactory = new LaunchPoolFactory(); - } - - function testCreatePool() public { - // Act: Call createPool function - uint256 poolId = poolFactory.createPool( - address(this), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - - // Assert: Check if the pool count increased - uint256 currentPoolId = poolFactory.getPoolCount(); - assertTrue(currentPoolId == 1, "Pool count is not 1"); - - // Assert: Check if the pool id return the pool address - address poolAddress = poolFactory.pools(poolId); - assertTrue(poolAddress != address(0), "Pool address is 0"); - - // Assert: Check if the pool address is valid - assertTrue(poolFactory.isPoolValid(poolAddress), "Pool is not valid"); - } - - function testCreatePoolWithInvalidProjectToken() public { - // Act: Call createPool function with invalid project token - // Assert: Expect revert - vm.expectRevert(LaunchPoolFactory.InvalidProjectTokenAddress.selector); - uint256 poolId = poolFactory.createPool( - address(0), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - - // Assert: Check if the current pool count is 0 - uint256 currentPoolId = poolFactory.getPoolCount(); - assertTrue( - currentPoolId == 0, - "Pool created with invalid project token" - ); - - // Assert: Check if the pool id value is 0 - assertTrue(poolId == 0, "Pool id is not 0"); - } - - function testCreateSeveralPools() public { - // Act: Call createPool function several times - uint256 poolId1 = poolFactory.createPool( - address(this), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - uint256 poolId2 = poolFactory.createPool( - address(this), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - uint256 poolId3 = poolFactory.createPool( - address(this), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - uint256 poolId4 = poolFactory.createPool( - address(this), - address(this), - block.timestamp + 1000, - block.timestamp + 2000, - 1000, - 1000, - 1000 - ); - - // Assert: Check if the current pool count is 4 - uint256 currentPoolId = poolFactory.getPoolCount(); - assertTrue(currentPoolId == 4, "Pool count is not 4"); - - // Assert: Check if the pool id increase sequentially - assertTrue( - poolId1 == 1 && poolId2 == 2 && poolId3 == 3 && poolId4 == 4, - "Pool id is not 1" - ); - } -} diff --git a/test/Launchpool/CumulativeExchangeRate.t.sol b/test/Launchpool/CumulativeExchangeRate.t.sol new file mode 100644 index 0000000..357db0d --- /dev/null +++ b/test/Launchpool/CumulativeExchangeRate.t.sol @@ -0,0 +1,637 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +// @todo: Improve testcase later on when implementation for valid vAsset +contract CumulativeExchangeRateTest is Test { + MockLaunchpool public launchpool; + MockERC20 public projectToken; + MockERC20 public vAsset; + MockERC20 public nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + uint256 constant BLOCK_TIME = 6 seconds; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + projectToken = new MockERC20("PROJECT", "PRO"); + vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + nativeAsset = new MockERC20("Native Token", "NAT"); + } + + function test_constant_emission_rate_with_one_staker() public { + // Arrange: deploy pool + uint128[] memory changeBlocks = new uint128[](1); + uint128 startBlock = uint128(block.number) + 1; + changeBlocks[0] = startBlock; + uint256[] memory emissionRateChanges = new uint256[](1); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + uint128 poolDurationBlocks = 70; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act: + // 1. Stake 1000 vTokens at pool start (same as max amount per staker) + uint256 stakeAmount = maxVTokensPerStaker; + vAsset.approve(address(launchpool), stakeAmount); + vm.roll(startBlock); + launchpool.stake(stakeAmount); + uint256 nativeStakeAmount = launchpool.totalNativeStake(); + + // Assert: + // 1. Check cumulative exchange rate at pool start (should be 0) + uint256 actualExchangeRate = launchpool.cumulativeExchangeRate(); + assertEq( + actualExchangeRate, + 0, + "Cumulative exchange rate is not 0 at pool start" + ); + + // 2. Call _getPendingExchangeRate() halfway through the pool (35 blocks) + vm.roll(startBlock + poolDurationBlocks / 2); + actualExchangeRate = launchpool.exposed_getPendingExchangeRate(); + uint256 expectedExchangeRate = (emissionRateChanges[0] * + (poolDurationBlocks / 2) * + scalingFactor) / nativeStakeAmount; + + assertEq( + actualExchangeRate, + expectedExchangeRate, + "Cumulative exchange rate different from expectation" + ); + } + + function test_constant_emission_rate_with_two_stakers_at_the_same_block() + public + { + // Arrange: deploy pool + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act: + // 1. I Stake 1000 vTokens at pool start (same as max amount per staker) + uint256 stakeAmount = maxVTokensPerStaker; + vAsset.approve(address(launchpool), stakeAmount); + vm.roll(startBlock); + launchpool.stake(stakeAmount); + stakeAmount = launchpool.totalNativeStake(); + + // 2. Someone stakes 500 vTokens at pool start + address someoneElse = makeAddr("someone"); + uint256 stakeAmount2 = maxVTokensPerStaker / 2; + vAsset.freeMintTo(someoneElse, stakeAmount2); + vm.startPrank(someoneElse); // acting as another investor + vAsset.approve(address(launchpool), stakeAmount2); + launchpool.stake(stakeAmount2); + vm.stopPrank(); // return to original investor/signer + stakeAmount2 = launchpool.totalNativeStake() - stakeAmount; + + // Assert: + // 1. Check cumulative exchange rate at pool start (should be 0 bcuz tickBlockDelta is 0) + uint256 actualExchangeRate = launchpool.cumulativeExchangeRate(); + assertEq( + actualExchangeRate, + 0, + "Cumulative exchange rate is not 0 at pool start" + ); + + // 2. Call _getPendingExchangeRate() halfway through the pool (35 blocks) + vm.roll(startBlock + poolDurationBlocks / 2); + actualExchangeRate = launchpool.exposed_getPendingExchangeRate(); + uint256 expectedExchangeRate = (emissionRateChanges[0] * + (poolDurationBlocks / 2) * + scalingFactor) / (stakeAmount + stakeAmount2); + assertEq( + actualExchangeRate, + expectedExchangeRate, + "Cumulative exchange rate different from expectation" + ); + } + + function test_constant_emission_rate_with_two_stakers_at_different_blocks() + public + { + // Arrange: deploy pool + uint128[] memory changeBlocks = new uint128[](1); + uint128 startBlock = uint128(block.number) + 1; + changeBlocks[0] = startBlock; + uint256[] memory emissionRateChanges = new uint256[](1); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + uint128 poolDurationBlocks = 70; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act: + // 1. I Stake 1000 vTokens at pool start (same as max amount per staker) + vm.roll(startBlock); + uint256 stakeAmount = maxVTokensPerStaker; + vAsset.approve(address(launchpool), stakeAmount); + launchpool.stake(stakeAmount); + stakeAmount = launchpool.totalNativeStake(); + + // 2. Someone stakes 500 vTokens at halfway throught the pool + vm.roll(startBlock + poolDurationBlocks / 2); + address someoneElse = makeAddr("someone"); + uint256 stakeAmount2 = maxVTokensPerStaker / 2; + vAsset.freeMintTo(someoneElse, stakeAmount2); + vm.startPrank(someoneElse); // acting as another investor + vAsset.approve(address(launchpool), stakeAmount2); + launchpool.stake(stakeAmount2); + + // Assert: + // 1. Call getCumulativeExchangeRate right after someoneElse stakes, at the same block, which is block 35 + // (there staking shouldn't has any effect on cumulativeExchangeRate yet) + uint256 actualExchangeRate = launchpool.cumulativeExchangeRate(); + uint256 expectedExchangeRate = (emissionRateChanges[0] * + (poolDurationBlocks / 2) * + scalingFactor) / (stakeAmount); + assertEq( + actualExchangeRate, + expectedExchangeRate, + "Cumulative exchange rate different from expectation" + ); + vm.stopPrank(); // return to original investor/signer + } + + function test_variable_emission_rate_with_one_staker() public { + // Arrange: deploy pool + uint128 poolDurationBlocks = uint128(14 days / BLOCK_TIME); + uint128 startBlock = uint128(block.number) + 1; + uint128 endBlock = startBlock + poolDurationBlocks; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128[] memory changeBlocks = new uint128[](3); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + poolDurationBlocks / 3; // change at 1/3 of pool duration + changeBlocks[2] = startBlock + (poolDurationBlocks * 3) / 4; // chagne at 2/3 of pool duration + uint256[] memory emissionRateChanges = new uint256[](3); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + emissionRateChanges[1] = 1e3 * (10 ** vAsset.decimals()); + emissionRateChanges[2] = 9e2 * (10 ** vAsset.decimals()); + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act: + // 1. I Stake 1000 vTokens at pool start (same as max amount per staker) + vm.roll(startBlock); + uint256 stakeAmount = maxVTokensPerStaker; + vAsset.approve(address(launchpool), stakeAmount); + launchpool.stake(stakeAmount); + stakeAmount = launchpool.totalNativeStake(); + + // Assert: + // 1. I Call get accumulated exchange rate right after staking + uint256 actualExchangeRate = launchpool.cumulativeExchangeRate(); + assertEq( + actualExchangeRate, + 0, + "Cumulative exchange rate should be 0 at pool start" + ); + + // 2. Call _getPendingRewardRate rate at halfway through the pool + vm.roll(startBlock + poolDurationBlocks / 2); + uint256 pendingExchangeRate = launchpool + .exposed_getPendingExchangeRate(); + // Calculate expected rate at halfway point + uint256 expectedPendingExchangeRate = ((emissionRateChanges[0] * + (changeBlocks[1] - changeBlocks[0]) + + emissionRateChanges[1] * + (startBlock + (poolDurationBlocks / 2) - changeBlocks[1])) * + scalingFactor) / // First period: from startBlock to first change + // Second period: from first change to halfway point + stakeAmount; + assertEq( + pendingExchangeRate, + expectedPendingExchangeRate, + "Cumulative exchange rate different from expectation at halfway through the pool" + ); + + // 3. Call _getPendingRewardRate rate at 6/7 duration of the pool + vm.roll(startBlock + (poolDurationBlocks * 6) / 7); + pendingExchangeRate = launchpool.exposed_getPendingExchangeRate(); + // Calculate expected rate at halfway point + expectedPendingExchangeRate = + ((emissionRateChanges[0] * + (changeBlocks[1] - changeBlocks[0]) + + emissionRateChanges[1] * + (changeBlocks[2] - changeBlocks[1]) + + emissionRateChanges[2] * + (startBlock + (poolDurationBlocks * 6) / 7 - changeBlocks[2])) * + scalingFactor) / // First period: from startBlock to first change (1/3 of pool duration) + // Second period: from first change to second change (2/3 of pool duration) + // Third period: from second chagne to 6/7 of pool duration + stakeAmount; + assertEq( + pendingExchangeRate, + expectedPendingExchangeRate, + "Cumulative exchange rate different from expectation at halfway through the pool" + ); + } + + function test_variable_emission_rate_with_two_stakers_at_different_blocks() + public + { + // Arrange: deploy pool + uint128 poolDurationBlocks = uint128(14 days / BLOCK_TIME); + uint128 startBlock = uint128(block.number) + 1; + uint128 endBlock = startBlock + poolDurationBlocks; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128[] memory changeBlocks = new uint128[](3); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + poolDurationBlocks / 3; // change at 1/3 of pool duration + changeBlocks[2] = startBlock + (poolDurationBlocks * 3) / 4; // change at 2/3 of pool duration + uint256[] memory emissionRateChanges = new uint256[](3); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + emissionRateChanges[1] = 1e3 * (10 ** vAsset.decimals()); + emissionRateChanges[2] = 9e2 * (10 ** vAsset.decimals()); + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act: + // 1. I Stake 1000 vTokens at pool start (same as max amount per staker) + vm.roll(startBlock); + uint256 stakeAmount = maxVTokensPerStaker; + vAsset.approve(address(launchpool), stakeAmount); + launchpool.stake(stakeAmount); + stakeAmount = launchpool.totalNativeStake(); + + // 2. At 3/7 of pool duration, someone stakes 999 vTokens + vm.roll(startBlock + (poolDurationBlocks * 3) / 7); + address someoneElse = makeAddr("someone"); + uint256 stakeAmount2 = maxVTokensPerStaker - 1; + vAsset.freeMintTo(someoneElse, stakeAmount2); + vm.startPrank(someoneElse); // acting as another investor + vAsset.approve(address(launchpool), stakeAmount2); + launchpool.stake(stakeAmount2); + vm.stopPrank(); + + stakeAmount2 = launchpool.totalNativeStake() - stakeAmount; + + // Assert: + // 1. Check cumulative exchange rate at the last block of the pool + vm.roll(startBlock + poolDurationBlocks); + uint256 pendingExchangeRate = launchpool + .exposed_getPendingExchangeRate(); + uint256 actualCumulativeExchangeRate = launchpool + .cumulativeExchangeRate() + pendingExchangeRate; + // Calculate expected rate at pool end + uint256 expectedCumulativeExchangeRate = ((emissionRateChanges[0] * + (changeBlocks[1] - changeBlocks[0]) + + emissionRateChanges[1] * + (startBlock + (poolDurationBlocks * 3) / 7 - changeBlocks[1])) * + scalingFactor) / // First period: from startBlock to first change of emission rate + // Second period: from first change to when someoneElse stakes + (stakeAmount) + + // Third period: from when someoneElse stakes to second change of emission rate + ((emissionRateChanges[1] * + (changeBlocks[2] - + (startBlock + (poolDurationBlocks * 3) / 7)) + + emissionRateChanges[2] * + (startBlock + poolDurationBlocks - changeBlocks[2])) * + scalingFactor) / + // Fourth period: from second chagne to the end of the pool + (stakeAmount + stakeAmount2); + assertEq( + actualCumulativeExchangeRate, + expectedCumulativeExchangeRate, + "Cumulative exchange rate different from expectation at the end of the pool" + ); + } + + function test_variable_emission_rate_with_4_stakers_at_different_blocks() + public + { + // Arrange: deploy pool with same config as previous tests + uint128 poolDurationBlocks = uint128(14 days / BLOCK_TIME); + uint128 startBlock = uint128(block.number) + 1; // Start later to allow pre-start actions + uint128 endBlock = startBlock + poolDurationBlocks; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + + uint128[] memory changeBlocks = new uint128[](3); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + poolDurationBlocks / 3; + changeBlocks[2] = startBlock + (poolDurationBlocks * 3) / 4; + + uint256[] memory emissionRateChanges = new uint256[](3); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + emissionRateChanges[1] = 1e3 * (10 ** vAsset.decimals()); + emissionRateChanges[2] = 9e2 * (10 ** vAsset.decimals()); + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e6 * (10 ** projectToken.decimals()) + ); + + // Create test addresses + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + address charlie = makeAddr("charlie"); + address dave = makeAddr("dave"); + + // Act: + // 1. First staker (alice) joins at block startBlock + 50 with 750 tokens + vm.roll(startBlock); + uint256 aliceStake = 750 * (10 ** vAsset.decimals()); + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + console.log( + "Adjusted cumulative exchange after staking: %d", + launchpool.cumulativeExchangeRate() + ); + vm.stopPrank(); + aliceStake = launchpool.totalNativeStake(); + + // 2. Bob joins right before first emission rate change with 300 tokens + vm.roll(changeBlocks[1] - 1); + uint256 bobStake = 300 * (10 ** vAsset.decimals()); + vAsset.freeMintTo(bob, bobStake); + vm.startPrank(bob); + vAsset.approve(address(launchpool), bobStake); + launchpool.stake(bobStake); + console.log( + "Adjusted cumulative exchange after staking: %d", + launchpool.cumulativeExchangeRate() + ); + vm.stopPrank(); + bobStake = launchpool.totalNativeStake() - aliceStake; + + // 3. Charlie joins at halfway through the pool with 523 tokens + vm.roll(startBlock + (poolDurationBlocks * 1) / 2); + uint256 charlieStake = 523 * (10 ** vAsset.decimals()); + vAsset.freeMintTo(charlie, charlieStake); + vm.prank(charlie); + vAsset.approve(address(launchpool), charlieStake); + vm.prank(charlie); + launchpool.stake(charlieStake); + charlieStake = launchpool.totalNativeStake() - aliceStake - bobStake; + + // 4. Dave joins after second rate change with remaining allowance + vm.roll(changeBlocks[2] + 100); + uint256 daveStake = maxVTokensPerStaker - + 50 * + (10 ** vAsset.decimals()); + vAsset.freeMintTo(dave, daveStake); + vm.prank(dave); + vAsset.approve(address(launchpool), daveStake); + vm.prank(dave); + launchpool.stake(daveStake); + daveStake = + launchpool.totalNativeStake() - + aliceStake - + bobStake - + charlieStake; + + // Calculate expected exchange rate segments + // First period: startBlock+50 to first change, Alice and Bob involved + uint256 period1Rate = ((emissionRateChanges[0] * + (changeBlocks[1] - 1 - startBlock) * + scalingFactor) / aliceStake) + + (((emissionRateChanges[0] * 1) * scalingFactor) / + (aliceStake + bobStake)); + + // Second period: first change to halfway, Alice and Bob involved + uint256 halfwayBlock = startBlock + poolDurationBlocks / 2; + uint256 period2Blocks = halfwayBlock - changeBlocks[1]; + uint256 period2TotalStake = aliceStake + bobStake; + uint256 period2Rate = ((emissionRateChanges[1] * period2Blocks) * + scalingFactor) / period2TotalStake; + + // Third period: halfway to second change, Alice, Bob, and Charlie + uint256 period3Blocks = changeBlocks[2] - halfwayBlock; + uint256 period3TotalStake = aliceStake + bobStake + charlieStake; + uint256 period3Rate = ((emissionRateChanges[1] * period3Blocks) * + scalingFactor) / period3TotalStake; + + // Fourth period: second change to when Dave stakes. Alice, Bob and Charlie involved + uint256 period4Blocks = 100; + uint256 period4TotalStake = aliceStake + bobStake + charlieStake; + uint256 period4Rate = ((emissionRateChanges[2] * period4Blocks) * + scalingFactor) / period4TotalStake; + + // Fifth period: After Dave stakes to the end of pool . Alice, Bob, Charlie, and Dave involved + uint256 period5Block = endBlock - (changeBlocks[2] + 100); + uint256 period5TotalStake = aliceStake + + bobStake + + charlieStake + + daveStake; + uint256 period5Stake = ((emissionRateChanges[2] * period5Block) * + scalingFactor) / period5TotalStake; + + // Sum all periods + uint256 expectedRate = period1Rate + + period2Rate + + period3Rate + + period4Rate + + period5Stake; + + // Assert final rates + vm.roll(endBlock); + uint256 pendingRate = launchpool.exposed_getPendingExchangeRate(); + uint256 finalRate = launchpool.cumulativeExchangeRate() + pendingRate; + + assertEq( + finalRate, + expectedRate, + "Cumulative exchange rate at pool end different from expectation" + ); + } + + function test_cummulative_different_if_emission_rate_static() public { + // Arrange: deploy pool with static emission rate + uint128[] memory changeBlocks = new uint128[](1); + uint128 startBlock = uint128(block.number) + 1; + changeBlocks[0] = startBlock; + uint256[] memory emissionRateChanges = new uint256[](1); + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); // Static emission rate + uint128 poolDurationBlocks = 70; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + projectToken.transfer( + address(launchpool), + 1e3 * (10 ** projectToken.decimals()) + ); + + // Act 1: Initial stake at pool start + address staker = makeAddr("staker"); + uint256 stakeAmount = maxVTokensPerStaker / 2; + vAsset.freeMintTo(staker, stakeAmount); + vm.startPrank(staker); + vAsset.approve(address(launchpool), stakeAmount); + vm.roll(startBlock); + launchpool.stake(stakeAmount); + vm.stopPrank(); + + // Initialize with some value + vm.roll(startBlock + 4); + uint256 initialCumulativeRate = launchpool.cumulativeExchangeRate(); + + // Act 2: Track rate changes for 15 iterations (4 blocks each) + uint256[] memory rateChanges = new uint256[](15); + uint256[] memory absoluteRates = new uint256[](15); + + for (uint256 i = 0; i < 15; i++) { + uint256 previousRate = i == 0 + ? initialCumulativeRate + : absoluteRates[i - 1]; + + // Roll forward 4 blocks + vm.roll(startBlock + 4 + (i + 1) * 4); + + // Get new cumulative exchange rate + uint256 newRate = launchpool.cumulativeExchangeRate(); + absoluteRates[i] = newRate; + + // Calculate the difference + rateChanges[i] = newRate - previousRate; + + // Log the values + console.log( + "Block %d: Rate: %d, Change: %d", + block.number, + newRate, + rateChanges[i] + ); + } + + // Assert: With static emission rate, the rate changes should be constant + // (allowing for small rounding differences) + uint256 firstChange = rateChanges[0]; + for (uint256 i = 1; i < 15; i++) { + assertApproxEqAbs( + rateChanges[i], + firstChange, + 100, // Small tolerance for rounding errors + "Rate change should be consistent with static emission rate" + ); + } + } +} diff --git a/test/Launchpool/EstimatedNativeExRateAtEnd.t.sol b/test/Launchpool/EstimatedNativeExRateAtEnd.t.sol new file mode 100644 index 0000000..2269ce9 --- /dev/null +++ b/test/Launchpool/EstimatedNativeExRateAtEnd.t.sol @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +import { SetupStakers } from "test/testutils/SetupStakers.sol"; + +contract EstimatedNativeExRateAtEndTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + MockXCMOracle mockOracle; + SetupStakers setupStakers = new SetupStakers(); + + address owner; + address platformAdmin; + + // Constants for testing + uint128 public START_BLOCK; + uint128 public END_BLOCK; + uint256 public constant MAX_VSTAKER = 1000 ether; + uint256 public constant BLOCK_TIME = 6 seconds; + uint128 public poolDurationBlocks = uint128(14 days) / uint128(BLOCK_TIME); + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); + + // Deploy mock XCM oracle with fixed exchange rate (1:1 initially) + mockOracle = MockXCMOracle( + mockOracleDeployer.deploy(1e18, 10, 0, 6) // 0% APY to control rates precisely + ); + + // Set start block in the future + START_BLOCK = uint128(block.number + 10); + END_BLOCK = START_BLOCK + poolDurationBlocks; + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Setup pool with needed tokens + uint256 requiredProjectTokens = poolDurationBlocks * emissionRates[0]; + projectToken.freeMintTo(address(launchpool), requiredProjectTokens); + + // Configure Launchpool + vm.prank(launchpool.platformAdminAddress()); + launchpool.setXCMOracleAddress(address(mockOracle)); + } + + // Test for the normal case where we have a non-zero gradient + function test_estimated_native_exrate_with_non_zero_gradient() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 2, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // First staking to establish a baseline rate + vm.prank(stakers[0]); + launchpool.stake(500 ether); + + // Move forward some blocks and simulate interest accrual + vm.roll(START_BLOCK + 100); + mockOracle.setExchangeRate(1.05e18); // 5% increase + + // Second stake to record a gradient + vm.prank(stakers[1]); + launchpool.stake(200 ether); + + // Verify a non-zero gradient was created + uint256 gradient = launchpool.avgNativeExRateGradient(); + console.log("Average native exchange rate gradient:", gradient); + assertTrue(gradient > 0, "Gradient should be non-zero"); + + // Calculate expected rate at end + uint256 lastExRate = launchpool.lastNativeExRate(); + uint256 blocksTilEnd = END_BLOCK - + launchpool.lastNativeExRateUpdateBlock(); + uint256 expectedRateAtEnd = lastExRate + (gradient * blocksTilEnd); + + // Get estimated rate at end using the contract function + uint256 actualEstimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + // Verify the calculation matches our expected value + assertEq( + actualEstimatedRate, + expectedRateAtEnd, + "Estimated exchange rate at end should match manual calculation" + ); + } + + // Test for the edge case specifically mentioned in the TODO comment + // When avgNativeExRateGradient is zero after pool end + function test_estimated_native_exrate_with_zero_gradient_after_pool_end() + public + { + // Create staker + address[] memory stakers = setupStakers.createAndApprove( + 1, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // Stake to establish initial state + vm.prank(stakers[0]); + launchpool.stake(300 ether); + + // FIX: Add a check to verify the stake was successful and native amount was recorded + assertGt( + launchpool.getStakerNativeAmount(stakers[0]), + 0, + "Staking should record a non-zero native amount" + ); + + // Record the initial exchange rate + uint256 initialExRate = launchpool.lastNativeExRate(); + uint128 initialUpdateBlock = launchpool.lastNativeExRateUpdateBlock(); + console.log("Initial exchange rate:", initialExRate); + + // Move past the end block + vm.roll(END_BLOCK + 10); + + // Force avgNativeExRateGradient to be 0 to trigger our edge case + launchpool.wild_setAvgNativeExRateGradient(0); + assertEq( + launchpool.avgNativeExRateGradient(), + 0, + "Gradient should now be zero" + ); + + // When setting the gradient to zero, ensure the lastNativeExRateUpdateBlock is sensible: + launchpool.wild_setLastNativeExRateUpdateBlock( + uint128(START_BLOCK + 5) + ); + launchpool.wild_setAvgNativeExRateGradient(0); + + // CRITICAL FIX: Ensure the blockNumber - lastNativeExRateUpdateBlock is not zero + // This avoids division by zero when calculating new gradient + vm.roll(END_BLOCK + 20); // Roll to a block further from lastNativeExRateUpdateBlock + + // Simulate a new exchange rate increase after the pool ends + uint256 newRate = (initialExRate * 110) / 100; // 10% higher + mockOracle.setExchangeRate(newRate); + + // Calculate what we expect the result to be based on the formula in the function + uint256 currentTokenByVToken = launchpool + .exposed_getTokenByVTokenWithoutFee(1e18); + uint256 expectedGradient = (currentTokenByVToken - initialExRate) / + (block.number - initialUpdateBlock); + uint256 expectedRateAtEnd = initialExRate + + (expectedGradient * (END_BLOCK - initialUpdateBlock)); + + // Get the estimate from the contract function + uint256 actualEstimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + console.log("Current rate after increase:", currentTokenByVToken); + console.log("Block diff:", block.number - initialUpdateBlock); + console.log("Calculated gradient:", expectedGradient); + console.log("Expected rate at end:", expectedRateAtEnd); + console.log("Actual estimated rate:", actualEstimatedRate); + + // Verify the calculation matches our expected value + assertApproxEqRel( + actualEstimatedRate, + expectedRateAtEnd, + 0.0001e18, // 0.01% slippage tolerance + "Estimated exchange rate should match our manual calculation" + ); + + // Most importantly, verify that the calculated gradient is not zero + assertTrue( + expectedGradient > 0, + "Calculated gradient must not be zero" + ); + } + + // Test to verify the gradient calculation is correct when gradient close to zero but not zero + function test_estimated_native_exrate_with_very_small_gradient() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 2, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // Stake to establish initial state + vm.prank(stakers[0]); + launchpool.stake(100 ether); + + // Move forward many blocks to create a very small gradient (tiny interest over long time) + vm.roll(START_BLOCK + 1000); + assertTrue( + block.number <= END_BLOCK, + "Block number should be before end block for this test" + ); + + // Set very small interest change (0.00001% APY) - very extreme case + uint256 smallIncreaseRate = (launchpool.lastNativeExRate() * 10000001) / + 10000000; + mockOracle.setExchangeRate(smallIncreaseRate); + + // Second stake to record the small gradient + vm.prank(stakers[1]); + launchpool.stake(50 ether); + + // Verify gradient is very small but not zero + uint256 smallGradient = launchpool.avgNativeExRateGradient(); + console.log("Very small gradient: ", smallGradient); + assertTrue( + smallGradient > 0, + "Gradient should be very small but not zero" + ); + + // Calculate expected exchange rate at end + uint256 lastExRate = launchpool.lastNativeExRate(); + uint256 blocksTilEnd = END_BLOCK - + launchpool.lastNativeExRateUpdateBlock(); + uint256 expectedRateAtEnd = lastExRate + (smallGradient * blocksTilEnd); + + // Get the estimate from the contract function + uint256 actualEstimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + assertEq( + actualEstimatedRate, + expectedRateAtEnd, + "Estimated exchange rate should work with very small gradients" + ); + } + + // Test to ensure that when calculating a new gradient in the edge case, + // we don't get a division by zero + function test_no_division_by_zero_in_new_gradient_calculation() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 1, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // Stake to establish initial state + vm.prank(stakers[0]); + launchpool.stake(500 ether); + + assertTrue( + launchpool.avgNativeExRateGradient() == 0, + "Gradient should still be zero" + ); + + vm.roll(END_BLOCK + 1); + + // Setting a different exchange rate + mockOracle.setExchangeRate(1.1e18); // 10% increase + + // This should not revert + uint256 estimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + // Just verify we got a reasonable result + assertTrue( + estimatedRate > 0, + "Estimated exchange rate should be positive" + ); + } + + // Test that the calculated gradient is never zero + function test_new_gradient_is_never_zero() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 1, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // Stake to establish initial state + vm.prank(stakers[0]); + launchpool.stake(200 ether); + + // Record initial values + uint256 initialExRate = launchpool.lastNativeExRate(); + uint128 initialUpdateBlock = launchpool.lastNativeExRateUpdateBlock(); + + // Move past the end block + vm.roll(END_BLOCK + 5); + + // Force avgNativeExRateGradient to be 0 to trigger our edge case + launchpool.wild_setAvgNativeExRateGradient(0); + + // Test with various tiny exchange rate changes to ensure gradient is never zero + for (uint i = 1; i <= 5; i++) { + // Set a tiny increase in exchange rate (0.00001% * i) + uint256 tinyIncrease = initialExRate + + (initialExRate * i) / + 10000000; + mockOracle.setExchangeRate(tinyIncrease); + + // Calculate the gradient that should be used + uint256 blockDiff = block.number - initialUpdateBlock; + uint256 newRate = launchpool.exposed_getTokenByVTokenWithoutFee( + 1e18 + ); + uint256 calculatedGradient = (newRate - initialExRate) / blockDiff; + + // Get the estimated exchange rate - this uses the edge case code + uint256 estimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + // Verify the calculated gradient is never zero + assertTrue( + calculatedGradient > 0, + "Calculated gradient should never be zero" + ); + + // Make sure the end result is reasonable - greater than the initial rate + assertTrue( + estimatedRate > initialExRate, + "Estimated rate should be greater than initial rate" + ); + + console.log( + string( + abi.encodePacked( + "Test case ", + vm.toString(i), + ": Calculated gradient = ", + vm.toString(calculatedGradient) + ) + ) + ); + } + } + + // Test behavior with extreme values to ensure robustness + function test_estimated_native_exrate_with_extreme_values() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 1, + address(launchpool), + address(vAsset) + ); + + // Very large lastNativeExRate + uint256 veryLargeRate = type(uint128).max; // Use large but not max uint256 to avoid overflow + + // Move to start block + vm.roll(START_BLOCK); + + // Set large initial exchange rate + launchpool.wild_setLastNativeExRate(veryLargeRate); + + // Stake with a very small amount + vm.prank(stakers[0]); + launchpool.stake(1); // Minimum possible stake + + console.log( + "Gradient after stake: ", + launchpool.avgNativeExRateGradient() + ); + + // Force zero gradient + launchpool.wild_setAvgNativeExRateGradient(0); + + // Move past end block + vm.roll(END_BLOCK + 10); + + // Setting a slightly larger exchange rate + mockOracle.setExchangeRate((veryLargeRate * 10002) / 10000); // Set an even higher rate + + // This should not underflow/overflow + uint256 estimatedRate = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + // It should be at least as large as the initial rate + assertTrue( + estimatedRate >= veryLargeRate, + "Estimated rate should be at least the initial large rate" + ); + console.log("Estimated rate with extreme values:", estimatedRate); + } + + // Test with a real world scenario that includes staking, unstaking, and claiming + // function test_real_world_scenario_with_zero_gradient_edge_case() public { + // // Create stakers + // address[] memory stakers = setupStakers.createAndApprove( + // 3, + // address(launchpool), + // address(vAsset) + // ); + + // // Move to start block + // vm.roll(START_BLOCK); + + // // Stakers stake various amounts + // vm.prank(stakers[0]); + // launchpool.stake(300 ether); + + // vm.prank(stakers[1]); + // launchpool.stake(400 ether); + // console.log( + // "********* Staker 1 native amount staked:", + // launchpool.getStakerNativeAmount(stakers[1]) + // ); + + // vm.prank(stakers[2]); + // launchpool.stake(200 ether); + + // // Move forward in time with some interest accrual + // vm.roll(START_BLOCK + poolDurationBlocks / 2); + // mockOracle.setExchangeRate(1.02e18); // 2% increase + + // // Second stake from staker 0 to establish a gradient + // vm.prank(stakers[0]); + // launchpool.stake(100 ether); + + // // Record the gradient we have + // uint256 midPoolGradient = launchpool.avgNativeExRateGradient(); + // console.log("Mid-pool gradient:", midPoolGradient); + // assertTrue(midPoolGradient > 0, "Mid-pool gradient should be positive"); + + // // Move to just past the end block + // vm.roll(END_BLOCK + 1); + + // // Get the estimated exchange rate for verification + // uint256 estimatedRateAtEnd = launchpool + // .exposed_getEstimatedNativeExRateAtEnd(); + // console.log("Estimated exchange rate at end:", estimatedRateAtEnd); + // assertTrue( + // estimatedRateAtEnd > 0, + // "Estimated rate at end should be positive" + // ); + + // // Now force the avgNativeExRateGradient to 0 to simulate the edge case + // launchpool.wild_setAvgNativeExRateGradient(0); + + // // Exchange rate continues to increase after pool ends + // mockOracle.setExchangeRate(1.04e18); // 4% total increase + + // // Stakers begin to unstake + // uint256 staker1Native = launchpool.getStakerNativeAmount(stakers[1]); + // uint256 withdrawable = launchpool.getWithdrawableVTokens(staker1Native); + // console.log("The address that were used to stake: ", stakers[1]); + // vm.prank(stakers[1]); + // launchpool.unstake(withdrawable); + // console.log("Staker 1 native tokens: ", staker1Native); + + // // Calculate a new gradient based on the current exchange rate + // uint256 newRate = launchpool.exposed_getTokenByVTokenWithoutFee(1e18); + // uint256 initialExRate = launchpool.lastNativeExRate(); + // uint256 blockDiff = block.number - + // launchpool.lastNativeExRateUpdateBlock(); + // uint256 newGradient = (newRate - initialExRate) / blockDiff; + + // // This is the key part of the test - verify that this new gradient is non-zero + // assertTrue( + // newGradient > 0, + // "New gradient calculated after pool end should be non-zero" + // ); + // console.log("New gradient calculated after pool end:", newGradient); + + // // Get new estimated rate - should now use the new gradient calculation + // uint256 newEstimatedRate = launchpool + // .exposed_getEstimatedNativeExRateAtEnd(); + // console.log( + // "New estimated exchange rate after recalculation:", + // newEstimatedRate + // ); + + // // Owner claims interest - this should work correctly with the new gradient + // uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + // launchpool.claimOwnerInterest(); + // uint256 ownerBalanceAfter = vAsset.balanceOf(owner); + + // // Verify owner was able to claim interest + // assertTrue( + // ownerBalanceAfter > ownerBalanceBefore, + // "Owner should be able to claim interest after recalculation with new gradient" + // ); + + // // Now let's have the remaining stakers unstake + // uint256 staker0Native = launchpool.getStakerNativeAmount(stakers[0]); + // uint256 withdrawable0 = launchpool.getWithdrawableVTokens( + // staker0Native + // ); + // console.log("Withdrawable amount for staker 0:", withdrawable0); + // vm.prank(stakers[0]); + // launchpool.unstake(withdrawable0); + // console.log("Staker 0 native tokens: ", staker0Native); + + // uint256 staker2Native = launchpool.getStakerNativeAmount(stakers[2]); + // uint256 withdrawable2 = launchpool.getWithdrawableVTokens( + // staker2Native + // ); + // vm.prank(stakers[2]); + // launchpool.unstake(withdrawable2); + // console.log("Staker 2 native tokens: ", staker2Native); + + // // Staker 1 withdraw leftover + // uint256 leftOverNative1 = launchpool.getStakerNativeAmount(stakers[1]); + // console.log( + // "Staker 1 leftover amount of native tokens: ", + // leftOverNative1 + // ); + // uint256 leftOverVTokens1 = launchpool.getWithdrawableVTokens( + // leftOverNative1 + // ); + // console.log( + // "Staker 1 withdrawable amount of leftover vTokens: ", + // leftOverVTokens1 + // ); + // vm.prank(stakers[1]); + // launchpool.unstake(leftOverVTokens1); + // console.log("Unstaked success"); + + // // Verify the pool is correctly emptied + // assertEq( + // launchpool.totalNativeStake(), + // 0, + // "Total native stake should be zero after all unstakes" + // ); + // } + + function test_zero_gradient_edge_case_realistic() public { + // Create stakers + address[] memory stakers = setupStakers.createAndApprove( + 3, + address(launchpool), + address(vAsset) + ); + + // Move to start block + vm.roll(START_BLOCK); + + // All stakers stake at the SAME BLOCK with the SAME RATE + // This naturally results in zero gradient since no rate change is observed + vm.prank(stakers[0]); + launchpool.stake(300 ether); + + vm.prank(stakers[1]); + launchpool.stake(400 ether); + + vm.prank(stakers[2]); + launchpool.stake(200 ether); + + // Verify gradient is zero (naturally) + assertEq( + launchpool.avgNativeExRateGradient(), + 0, + "Gradient should be zero when all staking happens at same rate" + ); + + // Move to just past the end block + vm.roll(END_BLOCK + 1); + + // Exchange rate increases after pool ends + mockOracle.setExchangeRate(1.04e18); // 4% increase + + // First unstake - this should trigger exchange rate update with new non-zero gradient + uint256 staker1Native = launchpool.getStakerNativeAmount(stakers[1]); + uint256 withdrawable = launchpool.getWithdrawableVTokens(staker1Native); + vm.prank(stakers[1]); + launchpool.unstake(withdrawable); + + // Verify gradient was updated and is no longer zero + assertTrue( + launchpool.avgNativeExRateGradient() > 0, + "Gradient should be updated after first unstake" + ); + + // Continue with remaining unstakes + uint256 staker0Native = launchpool.getStakerNativeAmount(stakers[0]); + uint256 withdrawable0 = launchpool.getWithdrawableVTokens( + staker0Native + ); + vm.prank(stakers[0]); + launchpool.unstake(withdrawable0); + + uint256 staker2Native = launchpool.getStakerNativeAmount(stakers[2]); + uint256 withdrawable2 = launchpool.getWithdrawableVTokens( + staker2Native + ); + vm.prank(stakers[2]); + launchpool.unstake(withdrawable2); + + // Verify pool is empty + assertApproxEqAbs( + launchpool.totalNativeStake(), + 0, + 100, + "Total native stake should be zero after all unstakes" + ); + } +} diff --git a/test/Launchpool/GeneralGetterFuncs.t.sol b/test/Launchpool/GeneralGetterFuncs.t.sol new file mode 100644 index 0000000..93bcc80 --- /dev/null +++ b/test/Launchpool/GeneralGetterFuncs.t.sol @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +// @todo: Improve testcase later on when implementation for valid vAsset +contract GeneralGetterFuncsTest is Test { + // Default pool init values, use different values in test cases if needed + MockERC20 public projectToken = new MockERC20("PROJECT", "PRO"); + MockERC20 public vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + MockERC20 public nativeAsset = + new MockERC20("Native Imaginary", "nImaginary"); + MockLaunchpool public launchpool; + uint128[] changeBlocks = new uint128[](1); + uint256[] emissionRateChanges = new uint256[](1); + uint256 public constant BLOCK_TIME = 6 seconds; + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint128 endBlock = startBlock + poolDurationBlocks; + uint256 maxVAssetPerStaker = 1e4 * (10 ** vAsset.decimals()); + uint256 maxStakers = 0; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + + constructor() { + changeBlocks[0] = startBlock; + emissionRateChanges[0] = 1e4 * (10 ** vAsset.decimals()); + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVAssetPerStaker, + changeBlocks, + emissionRateChanges + ); + vm.roll(startBlock); + } + + function test_get_total_staked() public { + // Act: Stake vTokens at pool start + uint256 stakeAmount = maxVAssetPerStaker - 1; + vAsset.approve(address(launchpool), stakeAmount); + launchpool.stake(stakeAmount); + + // Assert: Check total staked amount + uint256 retrievedStakeAmount = launchpool.getTotalStakedVTokens(); + assertEq( + retrievedStakeAmount, + stakeAmount, + "Total staked amount is not correct" + ); + + // Act 2: Stake vTokens at half of pool duration + uint256 stakeAmount2 = (maxVAssetPerStaker * 6) / 7; + vAsset.approve(address(launchpool), stakeAmount2); + launchpool.stake(stakeAmount2); + + // Assert 2: Check total staked amount + retrievedStakeAmount = launchpool.getTotalStakedVTokens(); + assertEq( + retrievedStakeAmount, + stakeAmount + stakeAmount2, + "Total staked amount is not correct after staking twice" + ); + } + + function test_get_emission_rate() public { + // Arrange: Set up a new launchpool with multiple rate changes + uint128[] memory _changeBlocks = new uint128[](3); + uint256[] memory _emissionRates = new uint256[](3); + + _changeBlocks[0] = startBlock; + _changeBlocks[1] = startBlock + poolDurationBlocks / 2; + _changeBlocks[2] = startBlock + (poolDurationBlocks * 3) / 4; + + _emissionRates[0] = 1000 * (10 ** vAsset.decimals()); + _emissionRates[1] = 500 * (10 ** vAsset.decimals()); + _emissionRates[2] = 250 * (10 ** vAsset.decimals()); + + // Roll to the past because launchpool enforce startBlock > block.number + vm.roll(startBlock - 1); + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVAssetPerStaker, + _changeBlocks, + _emissionRates + ); + + // Test initial emission rate + vm.roll(startBlock); + assertEq( + launchpool.getEmissionRate(), + _emissionRates[0], + "Initial emission rate incorrect" + ); + + // Test rate at first change block + vm.roll(_changeBlocks[1]); + assertEq( + launchpool.getEmissionRate(), + _emissionRates[1], + "Emission rate after first change incorrect" + ); + + // Test rate at second change block + vm.roll(_changeBlocks[2]); + assertEq( + launchpool.getEmissionRate(), + _emissionRates[2], + "Emission rate after second change incorrect" + ); + + // Test rate between change blocks + vm.roll(_changeBlocks[1] + 1); + assertEq( + launchpool.getEmissionRate(), + _emissionRates[1], + "Emission rate between changes incorrect" + ); + + // Test rate at end block + vm.roll(endBlock); + assertEq( + launchpool.getEmissionRate(), + 0, + "Emission rate at end block should be 0" + ); + + // Test rate after end block + vm.roll(endBlock + 1); + assertEq( + launchpool.getEmissionRate(), + 0, + "Emission rate after end block should be 0" + ); + } + + function test_get_pool_info() public { + // Act: + // Deposit project tokens into the pool + uint256 depositAmount = projectToken.balanceOf(address(this)); + projectToken.transfer(address(launchpool), depositAmount); + vm.roll(changeBlocks[0]); + + // Assert: + ( + uint256 _startBlock, + uint256 _endBlock, + uint256 _totalProjectToken, + uint256 _emissionRate + ) = launchpool.getPoolInfo(); + assertEq( + _startBlock, + startBlock, + "Start block is not identical to that passed into constructor" + ); + assertEq( + _endBlock, + endBlock, + "End block is not identical to that passed into constructor" + ); + assertEq( + _totalProjectToken, + depositAmount, + "Total project token is not identical to the amount deposited into the launchpool" + ); + assertEq( + _emissionRate, + emissionRateChanges[0], + "Emission rate is not identical to that passed into constructor" + ); + } + + function test_get_total_project_token() public { + // Act: Deposit project tokens to launchpool + uint256 depositAmount = projectToken.balanceOf(address(this)); + projectToken.transfer(address(launchpool), depositAmount); + + // Assert: Check launchpool's project token balance + uint256 projectTokenBalance = launchpool.getTotalProjectToken(); + assertEq( + projectTokenBalance, + depositAmount, + "Total project token balance is not correct" + ); + } + + function test_get_staking_range() public { + // Assert: + (uint256 _maxVAssetPerStaker, uint256 _maxStakers) = launchpool + .getStakingRange(); + + assertEq( + _maxVAssetPerStaker, + maxVAssetPerStaker, + "Max vAsset per staker is not correct" + ); + assertEq(_maxStakers, maxStakers, "Max stakers is not correct"); + } + + function test_get_claimable_project_token() public { + // Arrange: Set up a new launchpool with multiple rate changes + uint128 _poolDurationBlocks = uint128(21 days / BLOCK_TIME); + uint128 _startBlock = uint128(block.number) + 1; + uint128 _endBlock = _startBlock + _poolDurationBlocks; + + uint128[] memory _changeBlocks = new uint128[](4); + uint256[] memory _emissionRates = new uint256[](4); + + _changeBlocks[0] = _startBlock; + _changeBlocks[1] = _startBlock + _poolDurationBlocks / 2; + _changeBlocks[2] = _startBlock + (_poolDurationBlocks * 3) / 4; + _changeBlocks[3] = _startBlock + (_poolDurationBlocks * 9) / 10; + + _emissionRates[0] = 1000 * (10 ** vAsset.decimals()); + _emissionRates[1] = 500 * (10 ** vAsset.decimals()); + _emissionRates[2] = 250 * (10 ** vAsset.decimals()); + _emissionRates[3] = 100 * (10 ** vAsset.decimals()); + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + _startBlock, + _endBlock, + maxVAssetPerStaker, + _changeBlocks, + _emissionRates + ); + uint256 scalingFactor = launchpool.SCALING_FACTOR(); + + uint256 projectTokenBalance = projectToken.balanceOf(address(this)); + projectToken.transfer(address(launchpool), projectTokenBalance); + + // Create actors with different addresses + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + address dave = makeAddr("dave"); + + // Act: + // 1. Alice stakes 1e4 vTokens at pool start + 100 blocks + vm.roll(_startBlock + 100); + vm.startPrank(alice); + uint256 aliceStake = 1e4 * (10 ** vAsset.decimals()); + vAsset.freeMint(aliceStake); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // 2. Bob stakes 1 vToken at the block after 2nd change block + vm.roll(_changeBlocks[2] + 1); + vm.startPrank(bob); + uint256 bobStake = 1 * (10 ** vAsset.decimals()); + vAsset.freeMint(bobStake); + vAsset.approve(address(launchpool), bobStake); + launchpool.stake(bobStake); + vm.stopPrank(); + + // 3. Dave stakes another 1e4 vTokens at the block before 3rd change block + vm.roll(_changeBlocks[3] - 1); + vm.startPrank(dave); // Fixed: Use alice's prank instead of bob's + uint256 daveStake = 1e4 * (10 ** vAsset.decimals()); // Fixed: Use 1e4 instead of 1 + vAsset.freeMint(daveStake); + vAsset.approve(address(launchpool), daveStake); + launchpool.stake(daveStake); + vm.stopPrank(); + + // Assert: + // 1. Check claimable project token amount for Alice at end of pool + vm.roll(_endBlock); + uint256 actualAliceClaimables = launchpool.getClaimableProjectToken( + alice + ); + + // Calculate expected claimable project token amount for Alice + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 bobNativeStake = launchpool.getStakerNativeAmount(bob); + uint256 daveNativeStake = launchpool.getStakerNativeAmount(dave); + uint256 totalNativeStake = aliceNativeStake + + bobNativeStake + + daveNativeStake; + + // Calculate expected claimable project token amount for Alice + uint256 period1Blocks = _changeBlocks[1] - (_startBlock + 100); + uint256 period1ExchangeRate = ((_emissionRates[0] * period1Blocks) * + scalingFactor) / aliceNativeStake; + + uint256 period2Blocks = _changeBlocks[2] - _changeBlocks[1]; + uint256 period2ExchangeRate = ((_emissionRates[1] * period2Blocks) * + scalingFactor) / aliceNativeStake; + + uint256 period3Blocks = 1; + uint256 period3ExchangeRate = ((_emissionRates[2] * period3Blocks) * + scalingFactor) / aliceNativeStake; + + // Bob joins here + uint256 period4Blocks = _changeBlocks[3] - 1 - (_changeBlocks[2] + 1); + uint256 period4ExchangeRate = ((_emissionRates[2] * period4Blocks) * + scalingFactor) / (aliceNativeStake + bobNativeStake); + + // Dave joins here + uint256 period5Blocks = 1; + uint256 period5ExchangeRate = ((_emissionRates[2] * period5Blocks) * + scalingFactor) / + (aliceNativeStake + bobNativeStake + daveNativeStake); + + uint256 period6Blocks = _endBlock - _changeBlocks[3]; + uint256 period6ExchangeRate = ((_emissionRates[3] * period6Blocks) * + scalingFactor) / + (aliceNativeStake + bobNativeStake + daveNativeStake); + + uint256 expectedAliceClaimables = ((period1ExchangeRate + + period2ExchangeRate + + period3ExchangeRate + + period4ExchangeRate + + period5ExchangeRate + + period6ExchangeRate) * aliceNativeStake) / scalingFactor; + assertEq( + actualAliceClaimables, + expectedAliceClaimables, + "Claimable amount mismatch" + ); + } + + function test_get_active_block_delta() public { + vm.roll(startBlock + poolDurationBlocks / 2); + assertEq( + launchpool.exposed_getActiveBlockDelta(startBlock, block.number), + (poolDurationBlocks / 2) + ); + + // Assert active block delta exceed pool duration + vm.roll(endBlock + 1000); + assertEq( + launchpool.exposed_getActiveBlockDelta(startBlock, block.number), + poolDurationBlocks + ); + + // Assert active block delta 'from' after endBlock + assertEq( + launchpool.exposed_getActiveBlockDelta(endBlock + 1, endBlock + 2), + 0 + ); + } +} diff --git a/test/Launchpool/GeneralState.t.sol b/test/Launchpool/GeneralState.t.sol new file mode 100644 index 0000000..ba26c75 --- /dev/null +++ b/test/Launchpool/GeneralState.t.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +contract GeneralStateTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + MockXCMOracle xcmOracle; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + function test_intialized_scaling_factor() public view { + uint256 expScalingFactor = launchpool.BASE_PRECISION() / + (10 ** projectToken.decimals()); + + assertEq(launchpool.SCALING_FACTOR(), expScalingFactor); + } + + function test_intialized_one_vtoken_value() public view { + uint256 oneVToken = launchpool.ONE_VTOKEN(); + assertEq(oneVToken, 10 ** vAsset.decimals()); + } +} diff --git a/test/Launchpool/GetWithdrawableVTokens.t.sol b/test/Launchpool/GetWithdrawableVTokens.t.sol new file mode 100644 index 0000000..f3b9321 --- /dev/null +++ b/test/Launchpool/GetWithdrawableVTokens.t.sol @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +import { SetupStakers } from "test/testutils/SetupStakers.sol"; + +contract GetWithdrawableVTokensTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + MockXCMOracle mockOracle; + SetupStakers setupStakers = new SetupStakers(); + + address owner; + address platformAdmin; + address[] stakers; + + // Constants for testing + uint128 public START_BLOCK; + uint128 public END_BLOCK; + uint256 public constant MAX_VSTAKER = 1000 ether; + uint256 public constant BLOCK_TIME = 6 seconds; + uint128 public poolDurationBlocks = uint128(14 days) / uint128(BLOCK_TIME); + + // Initial exchange rate and stakes + uint256 public constant INITIAL_EXCHANGE_RATE = 1.2e18; // 1.2 native tokens per vToken + uint256 public constant INITIAL_STAKE_AMOUNT = 500 ether; + + function setUp() public { + owner = address(this); + platformAdmin = makeAddr("platformAdmin"); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); + + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracle = MockXCMOracle( + mockOracleDeployer.deploy(INITIAL_EXCHANGE_RATE, 10, 80000, 6) + ); + + // Set start block in the future + START_BLOCK = uint128(block.number + 10); + END_BLOCK = START_BLOCK + poolDurationBlocks; + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Setup pool with needed tokens + uint256 requiredProjectTokens = poolDurationBlocks * emissionRates[0]; + projectToken.freeMintTo(address(launchpool), requiredProjectTokens); + + // Configure Launchpool + launchpool.wild_setPlatformAdminAddress(platformAdmin); + launchpool.wild_setOwnerShareOfInterest(90); // 90% for owner, 10% as platform fee + + // Setup stakers + stakers = setupStakers.createAndApprove( + 3, + address(launchpool), + address(vAsset) + ); + } + + // Helper function to simulate staking with multiple users + function _setupStakingScenario() internal { + vm.roll(START_BLOCK); + + // Stake with multiple users + for (uint i = 0; i < stakers.length; i++) { + vm.prank(stakers[i]); + launchpool.stake(INITIAL_STAKE_AMOUNT); + } + } + + // Test getWithdrawableVTokens during active pool time + function test_get_withdrawable_v_tokens_during_pool_time() public { + _setupStakingScenario(); + + // Stake amount should convert back exactly to the same vTokens during pool time + uint256 nativeAmount = 300 ether; // Native token amount + uint256 expectedVTokens = (nativeAmount / INITIAL_EXCHANGE_RATE) * 1e18; // 300 / 1.2 = 250 vTokens + + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.0001e18, // 0.01% tolerance + "During pool time, native amount should convert correctly to vTokens" + ); + } + + // Test getWithdrawableVTokens after pool end with gradient=0 and updated exchange rate + function test_get_withdrawable_v_tokens_after_pool_end_with_zero_gradient() + public + { + _setupStakingScenario(); + + // Jump to pool end + vm.roll(END_BLOCK + 1); + + // First withdrawal should establish a gradient + uint256 nativeAmount = 300 ether; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + // At this point, avgNativeExRateGradient is likely 0 as no updates happened yet + // The function should update the rate internally and calculate correctly + + // Validate result still match expected conversion + uint256 expectedVTokens = (nativeAmount / INITIAL_EXCHANGE_RATE) * 1e18; + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.001e18, + "After pool end with zero gradient, should convert correctly" + ); + } + + // Test with increased exchange rate at end of pool + function test_get_withdrawable_v_tokens_with_changed_rate_at_pool_end() + public + { + _setupStakingScenario(); + + // First update exchange rate normally during pool + vm.roll(START_BLOCK + 100); + vm.prank(stakers[0]); + launchpool.stake(100 ether); + + // Simulate an increase in exchange rate over time + vm.roll(END_BLOCK); + uint256 increasedRate = (INITIAL_EXCHANGE_RATE * 110) / 100; // 10% increase + mockOracle.setExchangeRate(increasedRate); + + // Make a stake to update the rate gradient + vm.prank(stakers[1]); + launchpool.stake(50 ether); + + // Now check withdrawable amount after pool end + vm.roll(END_BLOCK + 1); + uint256 nativeAmount = 300 ether; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + // Expected vTokens should be calculated using the estimated rate at pool end + // This should be close to the increased rate + uint256 expectedVTokens = (nativeAmount * 1e18) / increasedRate; + + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.01e18, // 1% tolerance due to estimation + "After rate increase, should calculate withdrawable vTokens based on end rate" + ); + } + + // Test edge case: zero native amount + function test_get_withdrawable_v_tokens_zero_native_amount() public { + _setupStakingScenario(); + + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens(0); + assertEq( + withdrawableVTokens, + 0, + "Zero native amount should return zero withdrawable vTokens" + ); + } + + // Test edge case: very large native amount + function test_get_withdrawable_v_tokens_large_native_amount() public { + _setupStakingScenario(); + + // Add substantial vAssets to the pool + vAsset.freeMintTo(address(launchpool), 10000 ether); + + // Try to withdraw a very large amount larger than all native values in pool + uint256 largeNativeAmount = ((vAsset.balanceOf(address(launchpool)) * + INITIAL_EXCHANGE_RATE * + 110) / 100) / 1e18; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + largeNativeAmount + ); + + // Should be capped by total vAsset in pool + uint256 totalVAssetStaked = launchpool.getTotalStakedVTokens(); + assertEq( + withdrawableVTokens, + totalVAssetStaked, + "Very large native amount should be capped by total vAsset staked" + ); + } + + // Test case where calculation would exceed available vAssets + function test_get_withdrawable_v_tokens_exceed_available_v_assets() public { + _setupStakingScenario(); + + // Simulate some withdrawal, reducing vAsset balance but not updating totalNativeStake + uint256 vTokensToRemove = 700 ether; + vm.prank(address(launchpool)); + address fooAddr = makeAddr("foo"); // Foo address for burning tokens + vAsset.transfer(fooAddr, vTokensToRemove); // Send tokens to burn address instead + + // Try to withdraw all native stake (which would normally require more vAssets than available) + uint256 totalNative = launchpool.totalNativeStake(); + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + totalNative + ); + + // Withdrawable amount should be capped by available vAssets + uint256 remainingVAssets = vAsset.balanceOf(address(launchpool)); + assertEq( + withdrawableVTokens, + remainingVAssets, + "Withdrawable amount should be limited by available vAssets" + ); + } + + // Test with a changing exchange rate over time + function test_get_withdrawable_v_tokens_with_increasing_exchange_rate() + public + { + _setupStakingScenario(); + + // Simulate multiple exchange rate changes during the pool lifetime + uint256 steps = 10; + uint256[] memory increments = new uint256[](steps); + increments[0] = 5; // 5% increase + increments[1] = 3; // 3% increase + increments[2] = 7; // 7% increase + increments[3] = 2; // 2% increase + increments[4] = 4; // 4% increase + increments[5] = 5; // 5% increase + increments[6] = 3; // 3% increase + increments[7] = 7; // 7% increase + increments[8] = 2; // 2% increase + increments[9] = 4; // 4% increase + // Initial rate is 1.2, so at endBlock, it should be around 1.704 at pool end + + uint256 currentRate = INITIAL_EXCHANGE_RATE; + uint256 blockStep = poolDurationBlocks / steps; + + // Update exchange rate at intervals + for (uint i = 0; i < increments.length; i++) { + vm.roll(START_BLOCK + (blockStep * (i + 1))); + currentRate = (currentRate * (100 + increments[i])) / 100; + mockOracle.setExchangeRate(currentRate); + + // Make stakes to update the gradient + vm.prank(stakers[i % stakers.length]); + launchpool.stake(50 ether); + } + + // Check after pool end + vm.roll(END_BLOCK + 1); + uint256 nativeAmount = 300 ether; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + // Expected exchange rate at end should factor in all increases + // This test verifies the gradient is calculated correctly from multiple data points + uint256 expectedVTokens = (nativeAmount * 1e18) / currentRate; + + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.00001e18, // 0.001% tolerance for estimation differences + "Should calculate correct withdrawal amount after multiple rate changes" + ); + } + + // Test that the maxima of totalVAssetStaked works as expected + function test_get_withdrawable_v_tokens_max_total_v_asset_staked() public { + _setupStakingScenario(); + + // Intentionally lower the exchange rate to make withdrawal calculations exceed vAsset balance + mockOracle.setExchangeRate(INITIAL_EXCHANGE_RATE / 2); + + // Get total native stake and calculate how many vTokens it would require at the new lower rate + uint256 totalNative = launchpool.totalNativeStake(); + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + totalNative + ); + + // Should be capped by total vAsset in pool + uint256 totalVAssetStaked = launchpool.getTotalStakedVTokens(); + assertEq( + withdrawableVTokens, + totalVAssetStaked, + "Should be capped by total vAsset staked when exchange rate drops" + ); + } + + // Test calculation at the exact pool end block + function test_get_withdrawable_v_tokens_at_pool_end_block() public { + _setupStakingScenario(); + + // Move to exactly pool end block + vm.roll(END_BLOCK); + + // Increase exchange rate + uint256 newRate = (INITIAL_EXCHANGE_RATE * 110) / 100; + mockOracle.setExchangeRate(newRate); + + uint256 nativeAmount = 300 ether; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + // During pool time (including exactly at end block), should use simple conversion + uint256 expectedVTokens = (nativeAmount * 1e18) / newRate; + + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.001e18, + "At exact pool end, should use current exchange rate" + ); + } + + // Test correct behavior with multiple unstakes after pool end + function test_get_withdrawable_v_tokens_multiple_unstakes_after_pool_end() + public + { + _setupStakingScenario(); + + // Simulate increased exchange rate at end + vm.roll(END_BLOCK); + uint256 endRate = (INITIAL_EXCHANGE_RATE * 120) / 100; // 20% increase + mockOracle.setExchangeRate(endRate); + + // Move after pool end + vm.roll(END_BLOCK + 1); + + // First unstake to establish gradient + vm.startPrank(stakers[0]); + uint256 stakerNativeAmount = launchpool.getStakerNativeAmount( + stakers[0] + ); + uint256 withdrawableVTokens1 = launchpool.getWithdrawableVTokens( + stakerNativeAmount + ); + launchpool.unstake(withdrawableVTokens1); + vm.stopPrank(); + + // Check withdrawable amount for second staker + vm.startPrank(stakers[1]); + uint256 stakerNativeAmount2 = launchpool.getStakerNativeAmount( + stakers[1] + ); + uint256 withdrawableVTokens2 = launchpool.getWithdrawableVTokens( + stakerNativeAmount2 + ); + + // Should be consistent with first calculation (proportional to native amount) + uint256 expectedVTokens = (stakerNativeAmount2 * withdrawableVTokens1) / + stakerNativeAmount; + + assertApproxEqRel( + withdrawableVTokens2, + expectedVTokens, + 0.01e18, + "Second unstake should get consistent withdrawable amount after first unstake" + ); + vm.stopPrank(); + } + + // Test with updateNativeTokenExchangeRate forcing gradient update after pool end + function test_get_withdrawable_v_tokens_forced_gradient_update_after_pool_end() + public + { + _setupStakingScenario(); + + // Assert that gradient is still 0 + assertEq( + launchpool.avgNativeExRateGradient(), + 0, + "Gradient should still be 0 after 3 stakers staked at the same startBlock" + ); + + // Move to after pool end without any rate updates during pool + vm.roll(END_BLOCK + 1); + + // Force an update of the exchange rate gradient via unstake + uint256 newExchangeRate = 1.5e18; + mockOracle.setExchangeRate(newExchangeRate); + vm.prank(stakers[0]); + uint256 smallAmount = 10 ether; + launchpool.unstake(smallAmount); + + // Now check withdrawable amount for another user + uint256 nativeAmount = 300 ether; + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + // Should be based on the updated gradient now + uint256 exRateGradient = launchpool.avgNativeExRateGradient(); + uint256 expectedExRate = launchpool.lastNativeExRate() + + (exRateGradient * + (launchpool.endBlock() - + launchpool.lastNativeExRateUpdateBlock())); + + // Fix: Use the correct formula for expected vTokens + uint256 expectedVTokens = (nativeAmount * launchpool.ONE_VTOKEN()) / + expectedExRate; + assertApproxEqRel( + withdrawableVTokens, + expectedVTokens, + 0.01e18, + "After forced gradient update, should calculate based on updated rate" + ); + } + + // Test fuzz with random native amounts + function test_fuzz_get_withdrawable_v_tokens(uint256 nativeAmount) public { + // Bound to reasonable values to avoid overflow + nativeAmount = bound(nativeAmount, 0, 1000000 ether); + + _setupStakingScenario(); + + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + nativeAmount + ); + + if (nativeAmount == 0) { + // Zero input should return zero + assertEq( + withdrawableVTokens, + 0, + "Zero native amount should return zero vTokens" + ); + } else { + // Non-zero input should return proportional amount + uint256 expectedVTokens = (nativeAmount * 1e18) / + INITIAL_EXCHANGE_RATE; + uint256 totalVAssetStaked = launchpool.getTotalStakedVTokens(); + + // Result should be the min of calculated value and total staked + uint256 expectedResult = expectedVTokens; + if (expectedVTokens > totalVAssetStaked) { + expectedResult = totalVAssetStaked; + } + + assertApproxEqRel( + withdrawableVTokens, + expectedResult, + 0.0001e18, + "Should calculate correct withdrawable amount for any valid input" + ); + } + } +} diff --git a/test/Launchpool/Modifiers.t.sol b/test/Launchpool/Modifiers.t.sol new file mode 100644 index 0000000..a12ae2e --- /dev/null +++ b/test/Launchpool/Modifiers.t.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +contract ModifiersTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + function test_revert_stake_pool_not_active() public { + // Attempt staking before pool starts + vm.roll(START_BLOCK - 1); + vm.expectRevert( + abi.encodeWithSelector(Launchpool.MustBeDuringPoolTime.selector) + ); + launchpool.stake(MAX_VSTAKER); + + // Attempt staking after pool ends + vm.roll(END_BLOCK + 1); + vm.expectRevert( + abi.encodeWithSelector(Launchpool.MustBeDuringPoolTime.selector) + ); + launchpool.stake(MAX_VSTAKER); + } + + function test_revert_constructor_token_is_zero_address() public { + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Attempt to deploy launchpool with zero address for project token + vm.expectRevert( + abi.encodeWithSelector(Launchpool.ZeroAddress.selector) + ); + new MockLaunchpool( + owner, + address(0), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Attempt to deploy launchpool with zero address for vAsset + vm.expectRevert( + abi.encodeWithSelector(Launchpool.ZeroAddress.selector) + ); + new MockLaunchpool( + owner, + address(projectToken), + address(0), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Attempt to deploy launchpool with zero address for native asset + vm.expectRevert( + abi.encodeWithSelector(Launchpool.ZeroAddress.selector) + ); + new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(0), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + } +} diff --git a/test/Launchpool/NativeExchangeRate.t.sol b/test/Launchpool/NativeExchangeRate.t.sol new file mode 100644 index 0000000..5fb802d --- /dev/null +++ b/test/Launchpool/NativeExchangeRate.t.sol @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "../testutils/DeployMockXCMOracle.sol"; + +contract NativeExchangeRateTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Deploy mock XCM Oracle + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + // Test case: Initial exchange rate calculation + function test_initial_native_ex_rate() public { + uint256 initialRate = launchpool.exposed_getTokenByVTokenWithoutFee( + 1 * 10 ** vAsset.decimals() + ); + + // Assert if native exchange rate was intialized in constructor + assertEq( + launchpool.lastNativeExRate(), + initialRate, + "Initial rate hasn't been initialized correctly in constructor" + ); + + // Same assertion as above but at differnt block + vm.roll(START_BLOCK + 1); + assertEq( + launchpool.lastNativeExRate(), + initialRate, + "Initial rate hasn't been initialized correctly in constructor (different block)" + ); + } + + function test_update_native_ex_rate() public { + // Set initial conditions + vm.roll(START_BLOCK + 1); + launchpool.wild_setTickBlock(START_BLOCK); + + // Both values in wei (18 decimals) + uint256 currentExRate = launchpool.lastNativeExRate(); + uint256 increasedExRate = (currentExRate * 101) / 100; + uint256 vTokenAmount = 100 ether; + uint256 nativeAmount = (100 ether * increasedExRate) / + launchpool.ONE_VTOKEN(); + + // Call the function + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vTokenAmount + ); + + // Check that lastNativeExRate was set correctly + uint256 expectedExRate = (nativeAmount * launchpool.ONE_VTOKEN()) / + vTokenAmount; + assertEq( + launchpool.lastNativeExRate(), + expectedExRate, + "Initial exchange rate not set correctly" + ); + + // Sample count should still be 0 for first call + assertEq( + launchpool.nativeExRateSampleCount(), + 2, + "Sample count should be 2 after first call" + ); + } + + // Test case: No update if current block equals tickBlock + function test_no_update_on_same_block() public { + uint256 blockNum = START_BLOCK + 10; + vm.roll(blockNum); + + // Set tickBlock to current block + launchpool.wild_setTickBlock(uint128(blockNum)); + + // Set initial exchange rate + launchpool.wild_setLastNativeExRate(1 * launchpool.ONE_VTOKEN()); + + // Call with any values + launchpool.wild_updateNativeTokenExchangeRate( + 101 * 10 ** nativeAsset.decimals(), + 102 * 10 ** vAsset.decimals() + ); + + // Exchange rate should remain unchanged + assertEq( + launchpool.lastNativeExRate(), + 1 * launchpool.ONE_VTOKEN(), + "Exchange rate should not change when block == tickBlock" + ); + } + + // Test case: Gradient calculation between two exchange rate samples + function test_ex_rate_update() public { + // Set initial conditions + uint256 firstUpdateBlock = START_BLOCK + 10; + vm.roll(firstUpdateBlock); + + // First update to set initial exchange rate + uint256 vAssetAmount = 100 * 10 ** vAsset.decimals(); + uint256 nativeAmount = (vAssetAmount * + ((launchpool.lastNativeExRate() * 102) / 100)) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vAssetAmount + ); + // Set tick block after first update to mirror contract behaviour + launchpool.wild_setTickBlock(uint128(firstUpdateBlock)); + + uint256 initialRate = launchpool.lastNativeExRate(); + + // Move forward to the future + uint256 secondUpdateBlock = firstUpdateBlock + 15; + vm.roll(secondUpdateBlock); + + // Second update with different ex-rate + uint256 newVAssetAmount = vAssetAmount; + uint256 newNativeAmount = (newVAssetAmount * + ((initialRate * 105) / 100)) / launchpool.ONE_VTOKEN(); + + // Calculate expected new rate + uint256 newRate = (newNativeAmount * launchpool.ONE_VTOKEN()) / + newVAssetAmount; + + // Calculate expected average gradient + uint256 rateDelta = newRate - initialRate; + uint256 blockDelta = secondUpdateBlock - firstUpdateBlock; + uint256 newGradient = rateDelta / blockDelta; + uint256 sampleCount = launchpool.nativeExRateSampleCount(); + uint256 expectedAvgGradient = (launchpool.avgNativeExRateGradient() * + (sampleCount - 1) + + newGradient) / (sampleCount); + + // Second update + launchpool.wild_updateNativeTokenExchangeRate( + newNativeAmount, + newVAssetAmount + ); + launchpool.wild_setTickBlock(uint128(secondUpdateBlock)); + + // Check exchange rate was updated + assertEq( + launchpool.lastNativeExRate(), + newRate, + "Native token ex-rate not updated correctly" + ); + + // Check gradient calculation + assertEq( + launchpool.avgNativeExRateGradient(), + expectedAvgGradient, + "Average native ex-rate gradient not calculated correctly" + ); + + // Sample count should be 1 now + assertEq( + launchpool.nativeExRateSampleCount(), + sampleCount + 1, + "Sample count should increase by 1 after update" + ); + } + + // Test case: Rolling average gradient calculation + function test_multiple_rolling_average_gradient_updates() public { + // First, set initial exchange rate and reset pool pool states to de-effect the constructor + uint256 initialRate = (105 * launchpool.ONE_VTOKEN()) / 100; + launchpool.wild_setLastNativeExRate(initialRate); + launchpool.wild_setNativeExRateSampleCount(1); + launchpool.wild_setTickBlock(START_BLOCK); + // launchpool.exposed_updateNativeTokenExchangeRate(100 ether, 100 ether); + + // Move forward + vm.roll(START_BLOCK + 15); + + // Second update + launchpool.wild_updateNativeTokenExchangeRate(110 ether, 100 ether); + + // Set sample count manually to test rolling average + launchpool.wild_setNativeExRateSampleCount(5); + launchpool.wild_setAvgNativeExRateGradient(2 ether); // 2 tokens per block + + // Store initial values for verification + uint256 avgGradient = 2 ether; + uint256 sampleCount = 5; + uint256 lastRate = (110 * launchpool.ONE_VTOKEN()) / 100; + uint256 lastBlock = START_BLOCK + 15; + + // Run multiple rolling average updates through a loop + uint256 numUpdates = 15; // Number of updates to perform + + for (uint256 i = 1; i <= numUpdates; i++) { + // Move forward by a variable number of blocks (3-7 blocks) + uint256 blockJump = 3 + (i % 5); + uint256 currentBlock = lastBlock + blockJump; + vm.roll(currentBlock); + + // Calculate next exchange rate with a variable rate increase + uint256 nativeAmount = (110 ether + i * 1e18); + uint256 vTokenAmount = 100 ether; + + // Update the exchange rate + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vTokenAmount + ); + + // Calculate the expected gradient and rolling average + uint256 newRate = (nativeAmount * launchpool.ONE_VTOKEN()) / + vTokenAmount; + uint256 rateDelta = newRate - lastRate; + uint256 blockDelta = currentBlock - lastBlock; + uint256 newGradient = rateDelta / blockDelta; + + // Update expected rolling average: (oldAvg * oldCount + newSample) / (oldCount + 1) + avgGradient = + (avgGradient * (sampleCount - 1) + newGradient) / + (sampleCount); + sampleCount++; + + // Update values for next iteration + lastRate = newRate; + lastBlock = currentBlock; + + assertApproxEqAbs( + launchpool.avgNativeExRateGradient(), + avgGradient, + 1e12, + string( + abi.encodePacked( + "Rolling average gradient incorrect at update ", + i + ) + ) + ); + + assertEq( + launchpool.nativeExRateSampleCount(), + sampleCount, + string(abi.encodePacked("Sample count incorrect at update ", i)) + ); + } + + // Final verification + assertApproxEqAbs( + launchpool.avgNativeExRateGradient(), + avgGradient, + 1e12, + "Final rolling average gradient calculation incorrect" + ); + + assertEq( + launchpool.nativeExRateSampleCount(), + 5 + numUpdates, + "Final sample count incorrect" + ); + } + + // Test case: Edge case with different token decimals (unlikely in practice) + function test_different_token_decimals() public { + // Create tokens with different decimals + MockERC20 nativeAsset_token6 = new MockERC20("6 Decimals", "T6"); + nativeAsset_token6.setDecimals(6); + MockERC20 vAsset_token18 = new MockERC20("18 Decimals", "T18"); + vAsset_token18.setDecimals(18); + + // Deploy new launchpool with these tokens + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + MockLaunchpool testPool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset_token18), // VAsset with 18 decimals + address(nativeAsset_token6), // Native asset with 6 decimals + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + vm.roll(START_BLOCK); + + // 1 token6 = 10^6, 1 token18 = 10^18 + uint256 vTokenAmount = 1 * 10 ** vAsset_token18.decimals(); // 1 token with 18 decimals + uint256 nativeAmount = (vTokenAmount * + ((testPool.lastNativeExRate() * 1001) / 1000)) / + testPool.ONE_VTOKEN(); + + // Check scaling factor is appropriate for 6 decimals + assertEq( + testPool.ONE_VTOKEN(), + 10 ** vAsset_token18.decimals(), + "Value of ONE_VTOKEN not properly initialized as expected" + ); + + vm.roll(START_BLOCK + 20); + testPool.wild_updateNativeTokenExchangeRate(nativeAmount, vTokenAmount); + uint256 expectedRate = (nativeAmount * testPool.ONE_VTOKEN()) / + vTokenAmount; + assertEq( + testPool.lastNativeExRate(), + expectedRate, + "Exchange rate calculation wrong with different decimals" + ); + } + + // Test case: Zero division protection + function test_zero_division_protection() public { + vm.roll(START_BLOCK + 10); + launchpool.wild_setTickBlock(START_BLOCK); + + // Try with zero vTokenAmount + vm.expectRevert(); // Should revert on division by zero + launchpool.wild_updateNativeTokenExchangeRate(100 ether, 0); + } + + // ==================== Fuzz Tests ==================== + + // Fuzz test for exchange rate calculation with varying inputs + function test_fuzz_ex_rate_calculation_at_varying_block_num( + uint256 nativeAmount, + uint256 vTokenAmount, + uint256 examineBlock + ) public { + uint256 expectedRate = (launchpool.lastNativeExRate() * 1001) / 1000; + console.log("expectedRate: %d", expectedRate); + vTokenAmount = bound(vTokenAmount, 1e6, 1e36); // Lower bound to 1e4 + nativeAmount = (vTokenAmount * expectedRate) / launchpool.ONE_VTOKEN(); + examineBlock = bound(examineBlock, START_BLOCK, END_BLOCK); + + vm.roll(examineBlock); + + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vTokenAmount + ); + + assertApproxEqAbs( + launchpool.lastNativeExRate(), + expectedRate, + 1e12, + "Fuzz: Exchange rate calculation failed" + ); + } + + // Fuzz test for gradient calculation with varying exchange rates + function test_fuzz_gradient_calculation( + uint256 initialNative, + uint256 initialVToken, + uint256 finalNative, + uint256 finalVToken, + uint64 blocksDelta + ) public { + // Bound inputs to reasonable values + initialVToken = bound(initialVToken, 1, 1e30); // Bound relative to initialNative + initialNative = bound(initialNative, initialVToken, 2e30); + finalNative = bound( + finalNative, + initialNative, + (initialNative * 110) / 100 + ); + finalVToken = initialVToken; + blocksDelta = uint64( + bound(blocksDelta, 1, END_BLOCK - START_BLOCK - 1) + ); + + // Override pools' initial rate + uint256 poolInitBlock = block.number; + uint256 initialRate = (initialNative * launchpool.ONE_VTOKEN()) / + initialVToken; + launchpool.wild_setLastNativeExRate(initialRate); + launchpool.wild_setNativeExRateSampleCount(1); + launchpool.wild_setLastNativeExRateUpdateBlock(uint128(poolInitBlock)); + + // // Advance to start block to start staking + // vm.roll(START_BLOCK); + + // Move forward to block START_BLOCK + blocksDelta + vm.roll(poolInitBlock + blocksDelta); + + // Set the new exchange rate + launchpool.wild_updateNativeTokenExchangeRate(finalNative, finalVToken); + uint256 finalRate = launchpool.lastNativeExRate(); + + // Calculate expected gradient + uint256 rateDelta; + if (finalRate >= initialRate) { + rateDelta = finalRate - initialRate; + uint256 expectedAvgGradient = rateDelta / blocksDelta; + + assertApproxEqAbs( + launchpool.avgNativeExRateGradient(), + expectedAvgGradient, + 10, // Small tolerance due to division rounding + "Fuzz: Rate delta calculation mismatch" + ); + } else { + revert("Fuzz: Final rate should be greater than initial rate"); + } + } + + // Additional fuzz test to ensure no overflow/underflow with extreme values + function test_fuzz_no_overflow_underflow( + uint256 nativeAmount, + uint256 vTokenAmount + ) public { + // Ensure non-zero vTokenAmount + nativeAmount = bound(vTokenAmount, 1, 1e36); + vTokenAmount = bound(vTokenAmount, 1, 1e36); + + // Set up for exchange rate calculation + vm.roll(START_BLOCK + 10); + launchpool.wild_setTickBlock(START_BLOCK); + + // This should execute without overflow/underflow + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vTokenAmount + ); + + // No assertion needed lol ; D - test passes if no revert + } + + function test_estimated_native_ex_rate_at_end() public { + console.log( + "Something wrong here and I will get to the bottom of it (1):", + launchpool.ONE_VTOKEN() + ); + uint256 poolInitBlock = block.number; + uint256 newRateBlock = START_BLOCK + 20; + + uint256 deltaBlocks = newRateBlock - poolInitBlock; + + // Get the latest vToken -> token rate from Oracle + uint256 oldRate = launchpool.lastNativeExRate(); + + // Increase the rate by 10% + uint256 newRate = (oldRate * 110) / 100; + + // Tweak new rate for the pool + uint256 vAssetAmount = 100 * 10 ** vAsset.decimals(); + uint256 nativeAmount = (vAssetAmount * newRate) / + launchpool.ONE_VTOKEN(); + + vm.roll(newRateBlock); + + launchpool.wild_updateNativeTokenExchangeRate( + nativeAmount, + vAssetAmount + ); + launchpool.wild_setLastNativeExRateUpdateBlock(uint128(newRateBlock)); + + // Get the estimated rate at the end + uint256 rateAtEnd = launchpool.exposed_getEstimatedNativeExRateAtEnd(); + assertTrue(rateAtEnd > newRate, "Rate at end should be higher"); + + uint256 gradient = (newRate - oldRate) / deltaBlocks; + uint256 expectedRateAtEnd = newRate + + (gradient * (END_BLOCK - newRateBlock)); + assertApproxEqAbs( + rateAtEnd, + expectedRateAtEnd, + 1e10, + "Rate at end different from expected" + ); + } + + // Test that the estimated rate does not change after pool end + function test_estimated_native_ex_rate_not_change_after_end() public { + vm.roll(START_BLOCK + 10); + + // Simulate investor stake (manually update native exchange rate) + uint256 initialRate = launchpool.lastNativeExRate(); + uint256 rateAfterFirstStake = (initialRate * 105) / 100; + uint256 vAssetAmount = 100 * 10 ** vAsset.decimals(); + uint256 firstStakeNativeAmount = (vAssetAmount * rateAfterFirstStake) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + firstStakeNativeAmount, + vAssetAmount + ); + launchpool.wild_setTickBlock(START_BLOCK + 10); + + // Check that avg gradient has been updated (greater than 0) + assertTrue( + launchpool.avgNativeExRateGradient() > 0, + "Gradient should be greater than 0 after 1 investor staked" + ); + + // Tweak launchpool native exchange rate + vm.roll(START_BLOCK + 20); + uint256 newRate = (initialRate * 110) / 100; + uint256 newNativeAmount = (vAssetAmount * newRate) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + newNativeAmount, + vAssetAmount + ); + launchpool.wild_setTickBlock(START_BLOCK + 20); + uint256 expectedRateAtEnd = launchpool + .exposed_getEstimatedNativeExRateAtEnd(); + + // Move past end block + vm.roll(END_BLOCK + 10); + + // Try tweaking native exchange rate again and expect it to not update + uint256 afterEndRate = (initialRate * 110) / 100; + uint256 afterEndNativeAmount = (vAssetAmount * afterEndRate) / + launchpool.ONE_VTOKEN(); + uint256 avgGradientBeforeAction = launchpool.avgNativeExRateGradient(); + launchpool.wild_updateNativeTokenExchangeRate( + afterEndNativeAmount, + vAssetAmount + ); + launchpool.wild_setTickBlock(END_BLOCK + 10); + uint256 avgGradientAfterAction = launchpool.avgNativeExRateGradient(); + assertEq( + avgGradientAfterAction, + avgGradientBeforeAction, + "Avg gradient should not change after pool end if it's gt. than 0" + ); + assertEq( + launchpool.exposed_getEstimatedNativeExRateAtEnd(), + expectedRateAtEnd, + "Rate at end should not change after pool end if avg gradient is gt. than 0" + ); + assertEq( + launchpool.lastNativeExRate(), + newRate, + "Last native exchange rate should not change after pool end whatsoever" + ); + } + + // Test edge case where avg gradient is still 0 after end block (too few investors) + function test_estimated_native_ex_rate_change_after_end() public { + uint256 initialNativeExRateUpdateBlock = block.number; + + // Simulate investor stake at first block (should + // not update anything related to native token exchange rate) + uint256 initialRate = launchpool.lastNativeExRate(); + uint256 rateAfterFirstStake = (initialRate * 105) / 100; + uint256 vAssetAmount = 100 * 10 ** vAsset.decimals(); + uint256 firstStakeNativeAmount = (vAssetAmount * rateAfterFirstStake) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + firstStakeNativeAmount, + vAssetAmount + ); + + // Check that avg gradient has not been updated (greater than 0) + assertEq( + launchpool.avgNativeExRateGradient(), + 0, + "Gradient should still be 0 if investor stakes at start block" + ); + // Check that lastNativeExRate has not been updated + assertEq( + launchpool.lastNativeExRate(), + initialRate, + "Native exchange rate should not change if investor staked at start block" + ); + + uint256 deltaBlocksAfterAction = END_BLOCK + + 10 - + initialNativeExRateUpdateBlock; + uint256 deltaBlocks = END_BLOCK - initialNativeExRateUpdateBlock; + + // Move past end block + vm.roll(END_BLOCK + 10); + + // Try tweaking native exchange rate again and expect pool to accept that number + uint256 afterEndRate = (initialRate * 110) / 100; + uint256 afterEndNativeAmount = (vAssetAmount * afterEndRate) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + afterEndNativeAmount, + vAssetAmount + ); + uint256 expectedAvgGradientAfterAction = (afterEndRate - initialRate) / + deltaBlocksAfterAction; + uint256 avgGradientAfterAction = launchpool.avgNativeExRateGradient(); + + uint256 expectedRateAtEnd = initialRate + + expectedAvgGradientAfterAction * + deltaBlocks; + + assertEq( + avgGradientAfterAction, + expectedAvgGradientAfterAction, + "Avg. gradient should be updated after pool end if it's still 0 by then" + ); + assertEq( + launchpool.exposed_getEstimatedNativeExRateAtEnd(), + expectedRateAtEnd, + "Rate at end should change when action is invoked after pool while avg. gradient is still 0" + ); + assertEq( + launchpool.lastNativeExRate(), + initialRate, + "Native exchange should not be updated after pool whatsoever" + ); + } + + function test_no_state_update_if_rate_dont_change() public { + uint256 initialRate = launchpool.lastNativeExRate(); + + // Legitimate update + vm.roll(START_BLOCK); + uint256 newRate = (initialRate * 10001) / 10000; + uint256 newVAmount = 1 * 10 ** vAsset.decimals(); + uint256 newNativeAmount = (newVAmount * newRate) / + launchpool.ONE_VTOKEN(); + launchpool.wild_updateNativeTokenExchangeRate( + newNativeAmount, + newVAmount + ); + + // Fault update (rate don't change) + uint256 lastNativeExRate = launchpool.lastNativeExRate(); + uint256 lastNativeExRateUpdateBlock = launchpool + .lastNativeExRateUpdateBlock(); + uint256 avgNativeExRateGradient = launchpool.avgNativeExRateGradient(); + uint256 poolDurationBlocks = END_BLOCK - START_BLOCK; + vm.roll(START_BLOCK + ((poolDurationBlocks * 2) / 3)); + launchpool.wild_updateNativeTokenExchangeRate( + newNativeAmount, + newVAmount + ); + + // Assert no state update + assertEq( + launchpool.lastNativeExRate(), + lastNativeExRate, + "Native exchange rate should not change if rate don't change" + ); + assertEq( + launchpool.lastNativeExRateUpdateBlock(), + lastNativeExRateUpdateBlock, + "Last native exchange rate update block should not change if rate don't change" + ); + assertEq( + launchpool.avgNativeExRateGradient(), + avgNativeExRateGradient, + "Avg. gradient should not change if rate don't change" + ); + } +} diff --git a/test/Launchpool/OwnerInterest.t.sol b/test/Launchpool/OwnerInterest.t.sol new file mode 100644 index 0000000..f56a959 --- /dev/null +++ b/test/Launchpool/OwnerInterest.t.sol @@ -0,0 +1,656 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { console } from "forge-std/console.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +import { SetupStakers } from "test/testutils/SetupStakers.sol"; + +contract OwnerInterestTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + MockXCMOracle mockOracle; + SetupStakers setupStakers = new SetupStakers(); + + address owner; + address platformAdmin; + address staker1; + address staker2; + + // Constants for testing + uint128 public START_BLOCK; + uint128 public END_BLOCK; + uint256 public constant MAX_VSTAKER = 1000 ether; + uint256 public constant BLOCK_TIME = 6 seconds; + uint128 public poolDurationBlocks = uint128(14 days) / uint128(BLOCK_TIME); + uint128 public ownerShareOfInterest = 90; // 90% for owner, 10% as platform fee + + constructor() {} + + function setUp() public { + owner = address(this); + platformAdmin = makeAddr("platformAdmin"); + staker1 = makeAddr("staker1"); + staker2 = makeAddr("staker2"); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); + + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracle = MockXCMOracle( + mockOracleDeployer.deploy(1.2e18, 10, 80000, 6) + ); + + // Set start block in the future + START_BLOCK = uint128(block.number + 10); + END_BLOCK = START_BLOCK + poolDurationBlocks; + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Setup pool with needed tokens + uint256 requiredProjectTokens = poolDurationBlocks * emissionRates[0]; + projectToken.freeMintTo(address(launchpool), requiredProjectTokens); + vAsset.freeMintTo(staker1, 1000 ether); + vAsset.freeMintTo(staker2, 1000 ether); + + // Configure Launchpool + launchpool.wild_setPlatformAdminAddress(platformAdmin); + // launchpool.setXCMOracleAddress(address(xcmOracle)); + launchpool.wild_setOwnerShareOfInterest(ownerShareOfInterest); + } + + // Helper function to setup staking with interest simulation + function _setupStakingScenario(uint256 interestPercentage) internal { + address[] memory stakers = setupStakers.createAndApprove( + 2, + address(launchpool), + address(vAsset) + ); + staker1 = stakers[0]; + staker2 = stakers[1]; + + // Simulate staking from both stakers + vm.roll(START_BLOCK); + + uint256 stakeAmount = 500 ether; + vm.prank(staker1); + launchpool.stake(stakeAmount); + + vm.prank(staker2); + launchpool.stake(stakeAmount); + + console.log( + "********* Average native ex rate gradient after 2 stakes: %d", + launchpool.avgNativeExRateGradient() + ); + + // Simulate interest accrual + vm.roll(END_BLOCK); + uint256 lastExRate = mockOracle.getLastSetExchangeRate(); + uint256 newRate = (lastExRate * (100 + interestPercentage)) / 100; + mockOracle.setExchangeRate(newRate); + } + + // Test basic interest claiming functionality - kept as is, as per the instruction + function test_claim_owner_interest_success() public { + address[] memory stakers = setupStakers.createAndApprove( + 1, + address(launchpool), + address(vAsset) + ); + vm.roll(START_BLOCK); + uint256 stakeAmount = 500 * (10 ** vAsset.decimals()); + vm.prank(stakers[0]); + launchpool.stake(500 ether); + + // Simulate 1% interest accrual til end block + vm.roll(END_BLOCK); + uint256 lastExRate = mockOracle.getLastSetExchangeRate(); + mockOracle.setExchangeRate((lastExRate * (100 + 1)) / 100); + + // Jump to after pool end + + // Record balances before claim + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + uint256 platformBalanceBefore = vAsset.balanceOf(platformAdmin); + uint256 poolBalanceBefore = vAsset.balanceOf(address(launchpool)); + + // Get expected amounts + (uint256 ownerClaims, uint256 platformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + // Total interest should be about 20% of 300 ether = 60 ether + uint256 totalInterest = ownerClaims + platformFee; + // uint256 investorVAssets = launchpool.exposed_getVTokenByTokenWithoutFee( + // launchpool.totalNativeStake() + // ); + assertApproxEqRel( + totalInterest, + // vAsset.balanceOf(address(launchpool)) - investorVAssets, + (stakeAmount * 1) / 100, + 0.01e18, // 1% difference tolerance between expected and actual value + "Total interest should be close to 20% of staked amount" + ); + + // Owner claims interest + launchpool.claimOwnerInterest(); + + // Verify balances after claim + assertEq( + vAsset.balanceOf(owner), + ownerBalanceBefore + ownerClaims, + "Owner should receive correct amount of interest" + ); + + assertEq( + vAsset.balanceOf(platformAdmin), + platformBalanceBefore + platformFee, + "Platform admin should receive correct fee" + ); + + assertEq( + vAsset.balanceOf(address(launchpool)), + poolBalanceBefore - ownerClaims - platformFee, + "Pool balance should be reduced by claimed amounts" + ); + + // Verify correct split according to ownerShareOfInterest + assertApproxEqRel( + ownerClaims, + (totalInterest * ownerShareOfInterest) / 100, + 0.01e18, + "Owner claims should be correct percentage of interest" + ); + } + + // Test claiming when there's no interest + function test_claim_with_no_interest() public { + // Setup staking with 0% interest + _setupStakingScenario(0); + + vm.roll(END_BLOCK + 1); + + // Record balances before claim + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + uint256 platformBalanceBefore = vAsset.balanceOf(platformAdmin); + + // Get claimable amounts + (uint256 ownerClaims, uint256 platformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + // Should be very close to zero + assertLe( + ownerClaims + platformFee, + 0.01 ether, + "Total claimable amount should be near zero with no interest" + ); + + // Owner claims interest + launchpool.claimOwnerInterest(); + + // Verify minimal or no changes in balances (might be small rounding differences) + assertApproxEqAbs( + vAsset.balanceOf(owner), + ownerBalanceBefore, + 0.01 ether, + "Owner balance should barely change when no interest" + ); + + assertApproxEqAbs( + vAsset.balanceOf(platformAdmin), + platformBalanceBefore, + 0.01 ether, + "Platform admin balance should barely change when no interest" + ); + } + + // Test claiming with varying interest percentages + function test_claim_with_different_owner_interest_splits() public { + // Test with different owner shares + uint128[] memory shares = new uint128[](4); + shares[0] = 60; // 60% owner, 40% platform + shares[1] = 90; // 90% owner, 10% platform + shares[2] = 100; // 100% owner, 0% platform + shares[3] = 0; // 0% owner, 100% platform + + for (uint i = 0; i < shares.length; i++) { + // Reset scenario for each test case + if (i > 0) { + // Reset the test environment + setUp(); + } + + // Setup staking with 15% interest + _setupStakingScenario(1); + vm.roll(END_BLOCK + 1); + + // Record balances before claim + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + uint256 platformBalanceBefore = vAsset.balanceOf(platformAdmin); + + // Set new owner share + launchpool.wild_setOwnerShareOfInterest(shares[i]); + + // Get claimable amounts after setting new share + (uint256 ownerClaims, uint256 platformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + uint256 totalClaimable = ownerClaims + platformFee; + + // Owner claims interest + launchpool.claimOwnerInterest(); + + // Calculate expected amounts based on the total claimable + uint256 expectedOwnerAmount = (totalClaimable * shares[i]) / 100; + uint256 expectedPlatformAmount = totalClaimable - + expectedOwnerAmount; + + // Verify actual distribution + assertApproxEqAbs( + vAsset.balanceOf(owner) - ownerBalanceBefore, + expectedOwnerAmount, + 0.01 ether, + string( + abi.encodePacked( + "Owner should get ", + shares[i], + "% of interest" + ) + ) + ); + + assertApproxEqAbs( + vAsset.balanceOf(platformAdmin) - platformBalanceBefore, + expectedPlatformAmount, + 0.01 ether, + string( + abi.encodePacked( + "Platform should get ", + 100 - shares[i], + "% of interest" + ) + ) + ); + } + } + + // Test claiming multiple times with increasing interest + function test_multiple_owner_claims_with_increasing_interest() public { + // Initial setup with 10% interest + _setupStakingScenario(10); + + vm.roll(END_BLOCK + 1); + + // First claim + uint256 ownerBalanceBeforeFirst = vAsset.balanceOf(owner); + uint256 platformBalanceBeforeFirst = vAsset.balanceOf(platformAdmin); + + (uint256 firstOwnerClaims, uint256 firstPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + launchpool.claimOwnerInterest(); + + // Verify first claim + assertApproxEqAbs( + vAsset.balanceOf(owner) - ownerBalanceBeforeFirst, + firstOwnerClaims, + 0.01 ether, + "First owner claim amount incorrect" + ); + + assertApproxEqAbs( + vAsset.balanceOf(platformAdmin) - platformBalanceBeforeFirst, + firstPlatformFee, + 0.01 ether, + "First platform fee amount incorrect" + ); + + // Simulate more interest accrual by increasing the exchange rate further + uint256 lastRate = mockOracle.getLastSetExchangeRate(); + uint256 newRate = (lastRate * 115) / 100; // Additional 15% increase + mockOracle.setExchangeRate(newRate); + + // Add more vAssets to the pool to simulate the interest accrual + uint256 additionalVAssets = (1000 ether * 15) / 100; // 15% more interest + vAsset.freeMintTo(address(launchpool), additionalVAssets); + + // Second claim + uint256 ownerBalanceBeforeSecond = vAsset.balanceOf(owner); + uint256 platformBalanceBeforeSecond = vAsset.balanceOf(platformAdmin); + + (uint256 secondOwnerClaims, uint256 secondPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + launchpool.claimOwnerInterest(); + + // Verify second claim + assertApproxEqAbs( + vAsset.balanceOf(owner) - ownerBalanceBeforeSecond, + secondOwnerClaims, + 0.01 ether, + "Second owner claim amount incorrect" + ); + + assertApproxEqAbs( + vAsset.balanceOf(platformAdmin) - platformBalanceBeforeSecond, + secondPlatformFee, + 0.01 ether, + "Second platform fee amount incorrect" + ); + + // The second claimed amount should be roughly related to the additional interest + assertApproxEqRel( + secondOwnerClaims + secondPlatformFee, + additionalVAssets, + 0.1e18, + "Second total claim should match additional interest" + ); + } + + // Test claiming when some users haven't unstaked + function test_claim_with_active_stakers() public { + // Setup staking scenario with 15% interest + _setupStakingScenario(15); + + // Advance to after pool end + vm.roll(END_BLOCK + 1); + + // Get initial claimable amounts + (uint256 initialOwnerClaims, uint256 initialPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + uint256 initialTotalClaims = initialOwnerClaims + initialPlatformFee; + + // Staker1 unstakes + vm.startPrank(staker1); + uint256 staker1WithdrawableAmount = launchpool.getWithdrawableVTokens( + launchpool.getStakerNativeAmount(staker1) + ); + console.log( + "vAssets in the pool before staker 1 unstaked: %d", + vAsset.balanceOf(address(launchpool)) + ); + launchpool.unstake(staker1WithdrawableAmount); + vm.stopPrank(); + console.log( + "Avg native ex rate gradient after staker 1 unstaked: %d", + launchpool.avgNativeExRateGradient() + ); + console.log( + "Remaining vAssets in the pool after staker 1 unstaked: %d", + vAsset.balanceOf(address(launchpool)) + ); + + // But staker2 hasn't unstaked yet + + // Owner claims interest + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + launchpool.claimOwnerInterest(); + uint256 firstClaimAmount = vAsset.balanceOf(owner) - ownerBalanceBefore; + + // Verify owner can still claim interest even with active stakers + assertTrue( + firstClaimAmount > 0, + "Owner should be able to claim with active stakers" + ); + + // Now staker2 unstakes + vm.startPrank(staker2); + uint256 staker2WithdrawableAmount = launchpool.getWithdrawableVTokens( + launchpool.getStakerNativeAmount(staker2) + ); + launchpool.unstake(staker2WithdrawableAmount); + vm.stopPrank(); + + // Check if there's any additional claimable interest after all unstaking + (uint256 finalOwnerClaims, uint256 finalPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + if (finalOwnerClaims > 0 || finalPlatformFee > 0) { + // Owner claims again if there's anything to claim + uint256 ownerBalanceBeforeSecond = vAsset.balanceOf(owner); + launchpool.claimOwnerInterest(); + uint256 secondClaimAmount = vAsset.balanceOf(owner) - + ownerBalanceBeforeSecond; + + // Could be zero or small due to rounding + assertGe( + secondClaimAmount, + 0, + "Second claim should be zero or positive" + ); + } + } + + // Test claiming when contract is paused + function test_claim_when_paused() public { + // Setup staking with interest + _setupStakingScenario(10); + + vm.roll(END_BLOCK - 1); + + // Pause the contract + vm.prank(platformAdmin); + launchpool.pause(); + + // Verify contract is paused + assertTrue(launchpool.paused(), "Contract should be paused"); + + // Owner tries to claim + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + vm.prank(owner); + launchpool.claimOwnerInterest(); + uint256 claimAmount = vAsset.balanceOf(owner) - ownerBalanceBefore; + + // ClaimOwnerInterest should work even when paused since it's not using the whenNotPaused modifier + assertTrue( + claimAmount > 0, + "Owner should be able to claim when contract is paused" + ); + } + + function test_owner_interest_with_multiple_periods() public { + // SETUP: Initial staking period + address[] memory initialStakers = setupStakers.createAndApprove( + 3, + address(launchpool), + address(vAsset) + ); + + // First period staking + vm.roll(START_BLOCK); + for (uint i = 0; i < initialStakers.length; i++) { + vm.prank(initialStakers[i]); + launchpool.stake(300 ether); + } + + // First interest accrual (10%) + vm.roll(START_BLOCK + 300); + uint256 firstExRate = mockOracle.getLastSetExchangeRate(); + uint256 newRate1 = (firstExRate * 110) / 100; // 10% increase + mockOracle.setExchangeRate(newRate1); + + // FIRST CLAIM: Owner claims first period interest + uint256 ownerBalanceBefore1 = vAsset.balanceOf(owner); + uint256 platformBalanceBefore1 = vAsset.balanceOf(platformAdmin); + + (uint256 firstOwnerClaim, uint256 firstPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + uint256 firstTotalInterest = firstOwnerClaim + firstPlatformFee; + + launchpool.claimOwnerInterest(); + + // Verify interest distribution - 90% to owner, 10% to platform + assertApproxEqRel( + vAsset.balanceOf(owner) - ownerBalanceBefore1, + (firstTotalInterest * ownerShareOfInterest) / 100, + 0.0001e18, + "First owner claim should be 90% of total interest" + ); + + assertApproxEqRel( + vAsset.balanceOf(platformAdmin) - platformBalanceBefore1, + (firstTotalInterest * (100 - ownerShareOfInterest)) / 100, + 0.0001e18, + "First platform fee should be 10% of total interest" + ); + + // SECOND PERIOD: Some unstake, new stakers join, higher interest + vm.startPrank(initialStakers[0]); + console.log( + "*Pool vAsset balance prior to unstaking: %d", + vAsset.balanceOf(address(launchpool)) + ); + launchpool.unstake(300 ether - ((300 ether * 10) / 100)); // Less withdrawable vAssets due to increased interest + vm.stopPrank(); + console.log( + "*Pool vAsset balance after unstaking: %d", + vAsset.balanceOf(address(launchpool)) + ); + console.log( + "Cum. native -> project token exchange rate before unstaking: %d", + launchpool.cumulativeExchangeRate() + ); + + // New stakers join + address[] memory newStakers = setupStakers.createAndApprove( + 2, + address(launchpool), + address(vAsset) + ); + + vm.roll(START_BLOCK + 600); + console.log( + "Cum. native -> project token exchange rate after unstaking: %d", + launchpool.cumulativeExchangeRate() + + launchpool.exposed_getPendingExchangeRate() + ); + for (uint i = 0; i < newStakers.length; i++) { + vm.prank(newStakers[i]); + launchpool.stake(500 ether); + } + + // Second interest accrual (20%) + vm.roll(START_BLOCK + 700); + uint256 secondExRate = mockOracle.getLastSetExchangeRate(); + uint256 newRate2 = (secondExRate * 120) / 100; // 20% increase + mockOracle.setExchangeRate(newRate2); + + // SECOND CLAIM: Owner claims again + uint256 ownerBalanceBefore2 = vAsset.balanceOf(owner); + uint256 platformBalanceBefore2 = vAsset.balanceOf(platformAdmin); + + (uint256 secondOwnerClaim, uint256 secondPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + uint256 secondTotalInterest = secondOwnerClaim + secondPlatformFee; + + launchpool.claimOwnerInterest(); + + // Should be higher than first period due to more stakers and higher interest + assertTrue( + secondTotalInterest > firstTotalInterest, + "Second period interest should be higher than first" + ); + + // Verify second interest distribution follows same proportion + assertApproxEqRel( + vAsset.balanceOf(owner) - ownerBalanceBefore2, + (secondTotalInterest * ownerShareOfInterest) / 100, + 0.0001e18, + "Second owner claim should be 90% of total interest" + ); + + assertApproxEqRel( + vAsset.balanceOf(platformAdmin) - platformBalanceBefore2, + (secondTotalInterest * (100 - ownerShareOfInterest)) / 100, + 0.0001e18, + "Second platform fee should be 10% of total interest" + ); + } + + // Fuzz test with various interest percentages and owner shares + function test_fuzz_claim_owner_interest( + uint8 interestPercentage, + uint8 ownerSharePercentage + ) public { + // Bound inputs to reasonable values + interestPercentage = uint8(bound(interestPercentage, 1, 50)); // 1% to 50% interest + ownerSharePercentage = uint8(bound(ownerSharePercentage, 1, 100)); // 1% to 100% owner share + + // Setup staking with fuzzed interest percentage + _setupStakingScenario(interestPercentage); + + vm.roll(END_BLOCK + 1); + + // Set fuzzed owner share percentage + launchpool.wild_setOwnerShareOfInterest(ownerSharePercentage); + + // Record balances before claim + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + uint256 platformBalanceBefore = vAsset.balanceOf(platformAdmin); + + // Get expected claimable amounts + (uint256 ownerClaims, uint256 platformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + uint256 totalClaims = ownerClaims + platformFee; + + // Owner claims interest + launchpool.claimOwnerInterest(); + + // Verify actual splits according to ownerSharePercentage + uint256 actualOwnerClaim = vAsset.balanceOf(owner) - ownerBalanceBefore; + uint256 actualPlatformClaim = vAsset.balanceOf(platformAdmin) - + platformBalanceBefore; + + // Should be close to the expected percentages + assertApproxEqRel( + actualOwnerClaim, + (totalClaims * ownerSharePercentage) / 100, + 0.01e18, + "Owner claim should match expected percentage" + ); + + assertApproxEqRel( + actualPlatformClaim, + (totalClaims * (100 - ownerSharePercentage)) / 100, + 0.01e18, + "Platform claim should match expected percentage" + ); + + // Total claimed should match total claimable (within tolerance) + assertApproxEqAbs( + actualOwnerClaim + actualPlatformClaim, + totalClaims, + 0.01 ether, + "Total claimed should match total claimable" + ); + } +} diff --git a/test/Launchpool/Pause.t.sol b/test/Launchpool/Pause.t.sol new file mode 100644 index 0000000..125cdc2 --- /dev/null +++ b/test/Launchpool/Pause.t.sol @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; + +contract PauseTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + uint128 public poolDurationBlocks = END_BLOCK - START_BLOCK; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + vm.roll(START_BLOCK); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + function test_initially_not_paused() public view { + // Assert + assertEq( + launchpool.paused(), + false, + "Launchpool must not be paused initially" + ); + } + + function test_pause_success() public { + address platformAdmin = launchpool.platformAdminAddress(); + vm.prank(platformAdmin); + launchpool.pause(); + + assertEq(launchpool.paused(), true); + } + + function test_sequential_pause_unpause() public { + address platformAdmin = launchpool.platformAdminAddress(); + vm.prank(platformAdmin); + launchpool.pause(); + + address investor = makeAddr("investor"); + vm.startPrank(investor); + vAsset.freeMintTo(investor, MAX_VSTAKER); + vAsset.approve(address(launchpool), MAX_VSTAKER); + + // Assert + vm.expectRevert( + abi.encodeWithSelector(Pausable.EnforcedPause.selector) + ); + launchpool.stake(MAX_VSTAKER); + vm.stopPrank(); + + // Admin un-pauses, investor is able to stake + vm.prank(platformAdmin); + launchpool.unpause(); + + // Assert + assertEq( + launchpool.paused(), + false, + "Launchpool must not be paused after unpausing" + ); + + vm.prank(investor); + launchpool.stake(MAX_VSTAKER); + + // Admin pauses again, new investor would not be able to stake + vm.prank(platformAdmin); + launchpool.pause(); + address newInvestor = makeAddr("newInvestor"); + vm.startPrank(newInvestor); + vAsset.freeMintTo(newInvestor, MAX_VSTAKER); + vAsset.approve(address(launchpool), MAX_VSTAKER); + + // Assert + vm.expectRevert( + abi.encodeWithSelector(Pausable.EnforcedPause.selector) + ); + launchpool.stake(MAX_VSTAKER); + } + + function test_unstake_without_project_token_when_paused() public { + // Make investor + address investor = makeAddr("investor"); + vm.startPrank(investor); + uint256 investorStake = MAX_VSTAKER; + vAsset.freeMintTo(investor, investorStake); + vAsset.approve(address(launchpool), investorStake); + + // Stake + launchpool.stake(investorStake); + vm.stopPrank(); + + address platformAdmin = launchpool.platformAdminAddress(); + vm.prank(platformAdmin); + launchpool.pause(); + + // Unstake + vm.startPrank(investor); + vm.roll(START_BLOCK + (poolDurationBlocks * 4) / 5); + (uint256 investorNativeStake, ) = launchpool.stakers(investor); + uint256 withdrawableVAsset = launchpool.getWithdrawableVTokens( + investorNativeStake + ); + console.log( + "Withdrawable VAsset manually called: %d", + withdrawableVAsset + ); + + // Snapshot related state variables before test-withdrawal + uint256 totalPTokenBefore = launchpool.getTotalProjectToken(); + uint256 totalVAssetStakeBefore = launchpool.getTotalStakedVTokens(); + uint256 totalNativeStakeBefore = launchpool.totalNativeStake(); + uint256 investorVAssetBalanceBefore = vAsset.balanceOf(investor); + + launchpool.unstakeWithoutProjectToken(withdrawableVAsset); + vm.stopPrank(); + + // Assert + assertEq( + launchpool.getTotalProjectToken(), + totalPTokenBefore, + "Project token balance should not change after emergency withdrawal" + ); + + assertTrue( + launchpool.totalNativeStake() < totalNativeStakeBefore, + "Native stake should decrease after emergency withdrawal" + ); + + assertTrue( + launchpool.getTotalStakedVTokens() < totalVAssetStakeBefore, + "VAsset stake should decrease after emergency withdrawal" + ); + + assertEq( + vAsset.balanceOf(investor), + investorVAssetBalanceBefore + withdrawableVAsset, + "Investor should receive withdrawable VAsset after emergency withdrawal" + ); + } +} diff --git a/test/Launchpool/PlatformFee.t.sol b/test/Launchpool/PlatformFee.t.sol new file mode 100644 index 0000000..30f74c4 --- /dev/null +++ b/test/Launchpool/PlatformFee.t.sol @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; + +contract PlatformFeeTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + uint128 public poolDurationBlocks = END_BLOCK - START_BLOCK; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + vm.roll(START_BLOCK); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + function test_initial_platform_fee_claimed_status() public view { + assertEq( + launchpool.platformFeeClaimed(), + false, + "Platform fee should not be claimed initially" + ); + } + + function test_claim_success() public { + assert(launchpool.platformAdminAddress() != launchpool.owner()); + + // Simulate staking + address staker1 = makeAddr("staker1"); + address staker2 = makeAddr("staker2"); + vAsset.freeMintTo(staker1, MAX_VSTAKER); + vAsset.freeMintTo(staker2, MAX_VSTAKER); + + // Staker 1 stakes + vm.roll(START_BLOCK); + vm.startPrank(staker1); + uint256 staker1VAmount = MAX_VSTAKER / 2; + vAsset.approve(address(launchpool), staker1VAmount); + launchpool.stake(staker1VAmount); + vm.stopPrank(); + + // Staker 2 stakes + vm.roll(START_BLOCK + (poolDurationBlocks * 2) / 3); + vm.startPrank(staker2); + uint256 staker2VAmount = MAX_VSTAKER / 4; + vAsset.approve(address(launchpool), staker2VAmount); + launchpool.stake(staker2VAmount); + vm.stopPrank(); + + assertEq( + launchpool.getTotalStakedVTokens(), + staker1VAmount + staker2VAmount, + "Total staked vAssets should be sum of staker 1 and staker 2" + ); + + // Expect revert if attempt to claim before pool end + vm.roll(END_BLOCK); + console.log( + "Actual exrate at end block %d", + launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ) + ); + + address platformAdmin = launchpool.platformAdminAddress(); + vm.expectRevert( + abi.encodeWithSelector(Launchpool.MustBeAfterPoolEnd.selector) + ); + vm.prank(platformAdmin); + launchpool.claimPlatformFee(); + + // Snapshot state variables before action + uint256 poolBalanceBefore = vAsset.balanceOf(address(launchpool)); + uint256 platformBalanceBefore = vAsset.balanceOf(platformAdmin); + uint256 ownerBalanceBefore = vAsset.balanceOf(owner); + (uint256 ownerClaims, uint256 platformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + console.log("Platform fee amount in test: %d", platformFee); + + // Perform claim + vm.roll(END_BLOCK + 1); + console.log( + "Estimated native exrate at end: %d", + launchpool.exposed_getEstimatedNativeExRateAtEnd() + ); + vm.startPrank(platformAdmin); + launchpool.claimPlatformFee(); + vm.stopPrank(); + + // Assert + assertEq( + launchpool.platformFeeClaimed(), + true, + "Platform fee should be claimed after calling claimPlatformFee" + ); + assertEq( + vAsset.balanceOf(platformAdmin), + platformBalanceBefore + platformFee, + "Platform admin should receive claimed vAssets" + ); + + assertEq( + vAsset.balanceOf(address(launchpool)), + poolBalanceBefore - platformFee, + "Pool balance should decrease by claimed amount" + ); + + assertEq( + vAsset.balanceOf(owner), + ownerBalanceBefore, + "Owner balance should not change" + ); + + (uint256 newOwnerClaims, uint256 newPlatformFee) = launchpool + .exposed_getPlatformAndOwnerClaimableVAssets(); + + assertEq( + newPlatformFee, + 0, + "Platform and owner claimable vAssets should be zero after claiming" + ); + + assertEq( + newOwnerClaims, + ownerClaims, + "Owner claim should stay the same" + ); + } + + function test_revert_already_claimed() public { + // Simulate staking + address staker1 = makeAddr("staker1"); + address staker2 = makeAddr("staker2"); + vAsset.freeMintTo(staker1, MAX_VSTAKER); + vAsset.freeMintTo(staker2, MAX_VSTAKER); + + // Staker 1 stakes + vm.roll(START_BLOCK); + vm.startPrank(staker1); + uint256 staker1VAmount = MAX_VSTAKER / 2; + vAsset.approve(address(launchpool), staker1VAmount); + launchpool.stake(staker1VAmount); + vm.stopPrank(); + + // Staker 2 stakes + vm.roll(START_BLOCK + (poolDurationBlocks * 2) / 3); + vm.startPrank(staker2); + uint256 staker2VAmount = MAX_VSTAKER / 4; + vAsset.approve(address(launchpool), staker2VAmount); + launchpool.stake(staker2VAmount); + vm.stopPrank(); + + assertEq( + launchpool.getTotalStakedVTokens(), + staker1VAmount + staker2VAmount, + "Total staked vAssets should be sum of staker 1 and staker 2" + ); + + // Claim platform fee + vm.roll(END_BLOCK + 10000); + vm.startPrank(launchpool.platformAdminAddress()); + launchpool.claimPlatformFee(); + vm.stopPrank(); + + // Expect revert if attempt to claim again + vm.startPrank(launchpool.platformAdminAddress()); + vm.expectRevert( + abi.encodeWithSelector( + Launchpool.PlatformFeeAlreadyClaimed.selector + ) + ); + launchpool.claimPlatformFee(); + vm.stopPrank(); + } +} diff --git a/test/Launchpool/Stake.t.sol b/test/Launchpool/Stake.t.sol new file mode 100644 index 0000000..cb00333 --- /dev/null +++ b/test/Launchpool/Stake.t.sol @@ -0,0 +1,700 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; + +contract StakeTest is Test { + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + MockLaunchpool launchpool; + MockXCMOracle xcmOracle; + + function setUp() public { + projectToken = new MockERC20("PROJECT", "PRO"); + vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + nativeAsset = new MockERC20("Native Imaginary", "nImaginary"); + } + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + address mockXCMOracleAdr = mockOracleDeployer.deploy( + 1.2e18, + 10, + 80000, + 6 + ); + xcmOracle = MockXCMOracle(mockXCMOracleAdr); + } + + function test_basic_stake() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker + address alice = makeAddr("alice"); + uint256 aliceStake = maxVTokensPerStaker / 2; + vAsset.freeMintTo(alice, aliceStake); + + // Stake + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Assertions + assertEq( + vAsset.balanceOf(alice), + 0, + "Alice's vAsset balance should be 0 after staking" + ); + assertEq( + vAsset.balanceOf(address(launchpool)), + aliceStake, + "Launchpool's vAsset balance should equal the staked amount" + ); + + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 expectedNativeAmount = launchpool + .exposed_getTokenByVTokenWithoutFee(aliceStake); + assertEq( + aliceNativeStake, + expectedNativeAmount, + "Alice's native stake should match the converted amount" + ); + + assertEq( + launchpool.totalNativeStake(), + expectedNativeAmount, + "Total native stake should match Alice's stake" + ); + } + + function test_stake_multiple_users() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare stakers + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + + uint256 aliceStake = maxVTokensPerStaker / 2; + uint256 bobStake = maxVTokensPerStaker / 4; + + vAsset.freeMintTo(alice, aliceStake); + vAsset.freeMintTo(bob, bobStake); + + // Alice stakes + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Record Alice's native stake + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + + // Bob stakes + vm.startPrank(bob); + vAsset.approve(address(launchpool), bobStake); + launchpool.stake(bobStake); + vm.stopPrank(); + + // Record Bob's native stake + uint256 bobNativeStake = launchpool.getStakerNativeAmount(bob); + + // Assertions + assertEq( + vAsset.balanceOf(alice), + 0, + "Alice's vAsset balance should be 0 after staking" + ); + assertEq( + vAsset.balanceOf(bob), + 0, + "Bob's vAsset balance should be 0 after staking" + ); + assertEq( + vAsset.balanceOf(address(launchpool)), + aliceStake + bobStake, + "Launchpool's vAsset balance should equal the total staked amount" + ); + + assertEq( + launchpool.totalNativeStake(), + aliceNativeStake + bobNativeStake, + "Total native stake should match sum of Alice and Bob stakes" + ); + } + + function test_stake_zero_amount() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker + address alice = makeAddr("alice"); + vAsset.freeMintTo(alice, 100); + + // Attempt to stake zero amount + vm.startPrank(alice); + vAsset.approve(address(launchpool), 100); + + // Should revert with ZeroAmountNotAllowed + vm.expectRevert(Launchpool.ZeroAmountNotAllowed.selector); + launchpool.stake(0); + vm.stopPrank(); + } + + function test_stake_outside_pool_time() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 10; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Prepare staker + address alice = makeAddr("alice"); + uint256 aliceStake = maxVTokensPerStaker / 2; + vAsset.freeMintTo(alice, aliceStake); + + // Attempt to stake before start block + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + + // Should revert with MustBeDuringPoolTime + vm.expectRevert(Launchpool.MustBeDuringPoolTime.selector); + launchpool.stake(aliceStake); + + // Move to after end block + vm.roll(endBlock + 1); + + // Should still revert with MustBeDuringPoolTime + vm.expectRevert(Launchpool.MustBeDuringPoolTime.selector); + launchpool.stake(aliceStake); + vm.stopPrank(); + } + + function test_stake_multiple_times() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker + address alice = makeAddr("alice"); + uint256 firstStake = maxVTokensPerStaker / 4; + uint256 secondStake = maxVTokensPerStaker / 4; + vAsset.freeMintTo(alice, firstStake + secondStake); + + // First stake + vm.startPrank(alice); + vAsset.approve(address(launchpool), firstStake + secondStake); + launchpool.stake(firstStake); + + // Move forward a few blocks to accumulate rewards + vm.roll(startBlock + 10); + + // Check claimable tokens after some blocks + uint256 claimableBefore = launchpool.getClaimableProjectToken(alice); + assertTrue( + claimableBefore > 0, + "Should have accumulated some project tokens" + ); + + // Second stake - should claim accumulated rewards first + uint256 projectTokenBalanceBefore = projectToken.balanceOf(alice); + launchpool.stake(secondStake); + uint256 projectTokenBalanceAfter = projectToken.balanceOf(alice); + vm.stopPrank(); + + // Assertions + assertEq( + projectTokenBalanceAfter - projectTokenBalanceBefore, + claimableBefore, + "Should receive accumulated project tokens" + ); + assertEq( + vAsset.balanceOf(alice), + 0, + "Alice's vAsset balance should be 0 after staking twice" + ); + assertEq( + vAsset.balanceOf(address(launchpool)), + firstStake + secondStake, + "Launchpool should have received both stake amounts" + ); + + // Check accumulated rewards were reset + uint256 claimableAfter = launchpool.getClaimableProjectToken(alice); + assertEq( + claimableAfter, + 0, + "Claimable tokens should be reset after claiming during second stake" + ); + } + + function test_stake_with_exchange_rate_change() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare stakers + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + + uint256 aliceStake = maxVTokensPerStaker / 4; + uint256 bobStake = maxVTokensPerStaker / 4; + + vAsset.freeMintTo(alice, aliceStake); + vAsset.freeMintTo(bob, bobStake); + + // Alice stakes at initial exchange rate + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + + // Change exchange rate + xcmOracle.setExchangeRate(1.5e18); // 25% increase + + // Bob stakes at new exchange rate + vm.startPrank(bob); + vAsset.approve(address(launchpool), bobStake); + launchpool.stake(bobStake); + vm.stopPrank(); + + uint256 bobNativeStake = launchpool.getStakerNativeAmount(bob); + + // Assertions + assertTrue( + bobNativeStake > aliceNativeStake, + "Bob's native stake should be higher due to increased exchange rate" + ); + assertApproxEqRel( + bobNativeStake, + (aliceNativeStake * 5) / 4, + 0.01e18, + "Bob's native stake should be approximately 25% higher than Alice's" + ); + + // Ensure total native stake is sum of individual stakes + assertEq( + launchpool.totalNativeStake(), + aliceNativeStake + bobNativeStake, + "Total native stake should be sum of individual stakes" + ); + } + + function test_stake_more_than_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker with amount exactly equal to max + 1 + address alice = makeAddr("alice"); + uint256 aliceStake = maxVTokensPerStaker + 1; + vAsset.freeMintTo(alice, aliceStake); + + // Attempt to stake more than the maximum + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + + // Expect revert with ExceedMaxTokensPerStaker + vm.expectRevert(Launchpool.ExceedMaxTokensPerStaker.selector); + launchpool.stake(aliceStake); + vm.stopPrank(); + } + + function test_stack_stake_reach_more_than_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker + address alice = makeAddr("alice"); + uint256 firstStake = maxVTokensPerStaker / 2; + uint256 secondStake = maxVTokensPerStaker / 2 + 1; // This will exceed max when combined + vAsset.freeMintTo(alice, firstStake + secondStake); + + // First stake - should succeed + vm.startPrank(alice); + vAsset.approve(address(launchpool), firstStake + secondStake); + launchpool.stake(firstStake); + + // Second stake - should fail because it would exceed max + vm.expectRevert(Launchpool.ExceedMaxTokensPerStaker.selector); + launchpool.stake(secondStake); + vm.stopPrank(); + + // Verify first stake was successful + assertEq( + vAsset.balanceOf(address(launchpool)), + firstStake, + "Launchpool should have received only the first stake" + ); + } + + function test_stake_with_exact_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxNativeTokensPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxNativeTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Calculate the vToken amount that would convert to exactly maxNativeTokensPerStaker + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 aliceStake = (maxNativeTokensPerStaker * + (10 ** vAsset.decimals())) / nativePerVToken; + + // Prepare staker with amount that will convert to exactly max native tokens + address alice = makeAddr("alice"); + vAsset.freeMintTo(alice, aliceStake); + + // Attempt to stake exactly the maximum (in native token equivalent) + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Assertions + assertEq( + vAsset.balanceOf(alice), + 0, + "Alice's vAsset balance should be 0 after staking" + ); + assertEq( + vAsset.balanceOf(address(launchpool)), + aliceStake, + "Launchpool's vAsset balance should equal the staked amount" + ); + + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + aliceNativeStake, + maxNativeTokensPerStaker, + 0.01e18, + "Alice's native stake should be approximately equal to maxNativeTokensPerStaker" + ); + } + + function test_stack_stake_with_exact_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxNativeTokensPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxNativeTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Calculate the vToken amount that would convert to exactly maxNativeTokensPerStaker + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 aliceStake = (maxNativeTokensPerStaker * + (10 ** vAsset.decimals())) / nativePerVToken; + + // Prepare staker with amount that will convert to exactly max native tokens + address alice = makeAddr("alice"); + vAsset.freeMintTo(alice, aliceStake); + + // Attempt to stake exactly the maximum (in native token equivalent) + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake / 2); + launchpool.stake(aliceStake / 2 + 1); // Don't ask + vm.stopPrank(); + + // Assertions + assertEq( + vAsset.balanceOf(alice), + 0, + "Alice's vAsset balance should be 0 after staking" + ); + assertEq( + vAsset.balanceOf(address(launchpool)), + aliceStake, + "Launchpool's vAsset balance should equal the staked amount" + ); + + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + aliceNativeStake, + maxNativeTokensPerStaker, + 0.01e18, + "Alice's native stake should be approximately equal to maxNativeTokensPerStaker" + ); + } +} diff --git a/test/Launchpool/TokenDecimals.t.sol b/test/Launchpool/TokenDecimals.t.sol new file mode 100644 index 0000000..2bd4801 --- /dev/null +++ b/test/Launchpool/TokenDecimals.t.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { console } from "forge-std/console.sol"; + +contract ERC20WithoutDecimals { + constructor(string memory _name, string memory _symbol) {} +} + +contract TokenDecimalsTest is Test { + MockLaunchpool launchpool; + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + address owner; + + // Constants for testing + uint128 public START_BLOCK = 100; + uint128 public constant END_BLOCK = 1000; + uint256 public constant MAX_VSTAKER = 1000 ether; + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + mockOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function setUp() public { + owner = address(this); + + // Deploy mock tokens + projectToken = new MockERC20("Project Token", "PT"); + vAsset = new MockERC20("vAsset Token", "vToken"); + nativeAsset = new MockERC20("Native Asset", "Native"); // Different decimals to test scaling + + // Set start block in the future to ensure startBlock > current block + START_BLOCK = uint128(block.number + 10); + + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Deploy Launchpool with exposed functions + launchpool = new MockLaunchpool( + owner, + address(projectToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Mint tokens for testing + projectToken.freeMintTo(address(launchpool), 1000 ether); + vAsset.freeMintTo(address(this), 1000 ether); + nativeAsset.freeMintTo(address(this), 1000 ether); + + // Approve tokens for the launchpool + vAsset.approve(address(launchpool), type(uint256).max); + nativeAsset.approve(address(launchpool), type(uint256).max); + } + + function test_get_token_decimals() public view { + assertEq( + launchpool.exposed_getTokenDecimals(address(vAsset)), + IERC20Metadata(vAsset).decimals(), + "VAsset decimals mismatch" + ); + assertEq( + launchpool.exposed_getTokenDecimals(address(nativeAsset)), + IERC20Metadata(nativeAsset).decimals(), + "Native asset decimals mismatch" + ); + assertEq( + launchpool.exposed_getTokenDecimals(address(projectToken)), + IERC20Metadata(projectToken).decimals(), + "Project token decimals mismatch" + ); + } + + function test_revert_tokens_dont_have_decimals() public { + // Set up change blocks and emission rates for the Launchpool + uint128[] memory changeBlocks = new uint128[](1); + changeBlocks[0] = START_BLOCK; + + uint256[] memory emissionRates = new uint256[](1); + emissionRates[0] = 100 ether; + + // Expect revert when deploying Launchpool with project token without decimals + ERC20WithoutDecimals fakePToken = new ERC20WithoutDecimals( + "Fake Project Token", + "FPT" + ); + vm.expectRevert( + abi.encodeWithSelector( + Launchpool.FailedToReadTokenDecimals.selector + ) + ); + new MockLaunchpool( + owner, + address(fakePToken), + address(vAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + + // Expect revert when deploying Launchpool with native token without decimals + ERC20WithoutDecimals fakeVAsset = new ERC20WithoutDecimals( + "Fake Voucher Token", + "FVT" + ); + vm.expectRevert( + abi.encodeWithSelector( + Launchpool.FailedToReadTokenDecimals.selector + ) + ); + new MockLaunchpool( + owner, + address(projectToken), + address(fakeVAsset), + address(nativeAsset), + START_BLOCK, + END_BLOCK, + MAX_VSTAKER, + changeBlocks, + emissionRates + ); + } +} diff --git a/test/Launchpool/Unstake.t.sol b/test/Launchpool/Unstake.t.sol new file mode 100644 index 0000000..ff8696a --- /dev/null +++ b/test/Launchpool/Unstake.t.sol @@ -0,0 +1,851 @@ +// SPDX-License-Identifier: SEE LICENSE IN LICENSE +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { MockLaunchpool } from "@src/mocks/MockLaunchpool.sol"; +import { Launchpool } from "@src/non-upgradeable/Launchpool.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { DeployMockXCMOracle } from "test/testutils/DeployMockXCMOracle.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; + +contract UnstakeTest is Test { + MockERC20 projectToken; + MockERC20 vAsset; + MockERC20 nativeAsset; + DeployMockXCMOracle mockOracleDeployer = new DeployMockXCMOracle(); + MockLaunchpool launchpool; + MockXCMOracle xcmOracle; + + function setUp() public { + projectToken = new MockERC20("PROJECT", "PRO"); + vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + nativeAsset = new MockERC20("Native Imaginary", "nImaginary"); + // xcmOracle = new MockXCMOracle(); + } + + constructor() { + // Deploy mock xcm oracle with 1.2 initial rate, 10 block interval, 8% APY, 6 seconds block time + address mockXCMOracleAdr = mockOracleDeployer.deploy( + 1.2e18, + 10, + 80000, + 6 + ); + xcmOracle = MockXCMOracle(mockXCMOracleAdr); + } + + function test_unstake_success() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Act: Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + uint256 aliceStake = maxVTokensPerStaker / 2; // Use half the max to be safe + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Record important state before unstaking + uint256 stakedVTokens = launchpool.getTotalStakedVTokens(); + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + + // Roll to the end + vm.roll(endBlock); + + // Calculate the correct amount to unstake - ensure it's what can actually be withdrawn + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + assertLe( + withdrawableVTokens, + stakedVTokens, + "Withdrawable tokens must be <= staked tokens" + ); + + // Act: Unstake the withdrawable amount directly + vm.startPrank(alice); + launchpool.unstake(withdrawableVTokens); + vm.stopPrank(); + + // Assert + uint256 aliceClaimable = launchpool.getClaimableProjectToken(alice); + assertEq(aliceClaimable, 0); + + uint256 aliceVAssetBalance = vAsset.balanceOf(alice); + assertEq( + aliceVAssetBalance, + withdrawableVTokens, + "Alice should receive the correct amount of vAssets" + ); + + // Verify alice's stake is now 0 + assertEq( + launchpool.getStakerNativeAmount(alice), + 0, + "Alice's stake should be 0 after full unstake" + ); + } + + function test_unstake_more_than_staked() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Act: Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + uint256 aliceStake = maxVTokensPerStaker / 2; + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Record important state + uint256 stakedVTokens = launchpool.getTotalStakedVTokens(); + + vm.roll(endBlock); + + // Assert - try to unstake more than what was staked + vm.startPrank(alice); + vm.expectRevert(Launchpool.ExceedWithdrawableVTokens.selector); + launchpool.unstake(stakedVTokens + 1); + vm.stopPrank(); + } + + function test_unstake_before_end() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Act: Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + uint256 aliceStake = maxVTokensPerStaker / 2; + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Move forward but still before end + vm.roll(startBlock + 20); + + // Get withdrawable tokens directly from contract to avoid calculation issues + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + + // Act: Unstake the exact withdrawable amount + vm.startPrank(alice); + launchpool.unstake(withdrawableVTokens); + vm.stopPrank(); + + // Assert + uint256 aliceClaimable = launchpool.getClaimableProjectToken(alice); + assertEq(aliceClaimable, 0); + + uint256 aliceVAssetBalance = vAsset.balanceOf(alice); + assertEq( + aliceVAssetBalance, + withdrawableVTokens, + "Alice should receive the correct amount of vAssets" + ); + } + + function test_unstake_rapidly() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxVTokensPerStaker = 1e3 * (10 ** vAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxVTokensPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Act: Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + uint256 aliceStake = maxVTokensPerStaker / 2; + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + vm.roll(startBlock + 10); + + // Act: Unstake multiple times in small amounts + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 totalWithdrawableVTokens = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + + // Calculate unstake amount for 5 iterations + uint256 unstakeAmount = totalWithdrawableVTokens / 5; + uint256 initialVAssetBalance = vAsset.balanceOf(alice); + uint256 cumulativeUnstaked = 0; + + // First unstake + vm.startPrank(alice); + launchpool.unstake(unstakeAmount); + vm.stopPrank(); + + cumulativeUnstaked += unstakeAmount; + assertEq(vAsset.balanceOf(alice), initialVAssetBalance + unstakeAmount); + + // Second unstake after a few blocks + vm.roll(startBlock + 20); + + // Recalculate what's withdrawable after first unstake + aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 remainingWithdrawable = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + unstakeAmount = remainingWithdrawable > unstakeAmount + ? unstakeAmount + : remainingWithdrawable; + + vm.startPrank(alice); + launchpool.unstake(unstakeAmount); + vm.stopPrank(); + + cumulativeUnstaked += unstakeAmount; + assertApproxEqRel( + vAsset.balanceOf(alice), + initialVAssetBalance + cumulativeUnstaked, + 0.01e18, + "Alice should have received the correct cumulative amount of vAssets" + ); + + // Third unstake at pool end, if we still have tokens to unstake + vm.roll(endBlock); + + aliceNativeStake = launchpool.getStakerNativeAmount(alice); + if (aliceNativeStake > 0) { + remainingWithdrawable = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + if (remainingWithdrawable > 0) { + vm.startPrank(alice); + launchpool.unstake(remainingWithdrawable); + vm.stopPrank(); + + cumulativeUnstaked += remainingWithdrawable; + } + } + + // Verify final state + assertApproxEqRel( + vAsset.balanceOf(alice), + initialVAssetBalance + cumulativeUnstaked, + 0.01e18, + "Final vAsset balance should match initial + cumulative unstaked" + ); + + // Verify stake is entirely or nearly gone + uint256 remainingStake = launchpool.getStakerNativeAmount(alice); + assertLe( + remainingStake, + aliceNativeStake / 100, // Allow for tiny remainders due to rounding + "Remaining stake should be zero or near-zero" + ); + } + + function test_unstake_with_exchange_rate_change() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxTokenPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Act: Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + + // Calculate stake amount that converts to exactly maxTokenPerStaker + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 aliceStake = (maxTokenPerStaker * (10 ** vAsset.decimals())) / + nativePerVToken; + + vAsset.freeMintTo(alice, aliceStake); + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + uint256 totalNativeAtStart = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + totalNativeAtStart, + maxTokenPerStaker, + 0.01e18, + "Initial stake should be approximately max" + ); + + // Change exchange rate midway through pool + vm.roll(startBlock + poolDurationBlocks / 2); + + // Significant increase in exchange rate (50% increase) + xcmOracle.setExchangeRate(1.8e18); + + // Unstake half of what Alice has staked + uint256 totalVAssetStaked = launchpool.getTotalStakedVTokens(); + uint256 halfVAssetStaked = totalVAssetStaked / 2; + + vm.startPrank(alice); + launchpool.unstake(halfVAssetStaked); + vm.stopPrank(); + + // Check that Alice received the right amount of vAssets + assertEq(vAsset.balanceOf(alice), halfVAssetStaked); + + // Check that the remaining native token amount is updated correctly + uint256 remainingNative = launchpool.getStakerNativeAmount(alice); + + // The remaining native amount should be significantly less than half of the original amount + // because the exchange rate has increased + assertLt( + remainingNative, + totalNativeAtStart / 2, + "Remaining native amount should be less than half due to increased exchange rate" + ); + } + + function test_unstake_without_project_token() public { + // Setup + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxTokenPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Stake + address alice = makeAddr("alice"); + vm.roll(startBlock); + + uint256 aliceStake = 100 * (10 ** vAsset.decimals()); // Simple 100 tokens + vAsset.freeMintTo(alice, aliceStake); + + vm.startPrank(alice); + vAsset.approve(address(launchpool), aliceStake); + launchpool.stake(aliceStake); + vm.stopPrank(); + + // Roll forward to accumulate rewards + vm.roll(startBlock + 10); + + // Check that rewards have accumulated + uint256 claimableBefore = launchpool.getClaimableProjectToken(alice); + assertTrue(claimableBefore > 0, "Should have accumulated rewards"); + + // Record token balances before unstaking + uint256 projectBalanceBefore = projectToken.balanceOf(alice); + uint256 vAssetBalanceBefore = vAsset.balanceOf(alice); + + // Emergency unstake + vm.startPrank(alice); + launchpool.unstakeWithoutProjectToken(aliceStake); + vm.stopPrank(); + + // Verify Alice received her vTokens back + assertEq( + vAsset.balanceOf(alice), + vAssetBalanceBefore + aliceStake, + "Alice should get her vTokens back" + ); + + // Verify Alice did NOT receive any project tokens + assertEq( + projectToken.balanceOf(alice), + projectBalanceBefore, + "Alice should not receive any project tokens" + ); + + // Verify Alice's stake is gone + assertEq( + launchpool.getStakerNativeAmount(alice), + 0, + "Alice's stake should be zero after unstaking" + ); + + // Verify claimable tokens is also lost + assertEq( + launchpool.getClaimableProjectToken(alice), + 0, + "Claimable tokens should remain after emergency unstaking" + ); + } + + function test_unstake_then_stake_to_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxTokenPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker with plenty of tokens + address alice = makeAddr("alice"); + uint256 totalVTokens = 2e3 * (10 ** vAsset.decimals()); // Mint plenty of tokens + vAsset.freeMintTo(alice, totalVTokens); + + // Calculate initial stake to reach max + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 initialStakeVTokens = (maxTokenPerStaker * + (10 ** vAsset.decimals())) / nativePerVToken; + + // First stake to reach max + vm.startPrank(alice); + vAsset.approve(address(launchpool), totalVTokens); + launchpool.stake(initialStakeVTokens); + vm.stopPrank(); + + // Verify we've reached max + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + aliceNativeStake, + maxTokenPerStaker, + 0.01e18, + "Native stake should be approximately equal to maxTokenPerStaker" + ); + + // Try staking more, should fail + vm.startPrank(alice); + vm.expectRevert(Launchpool.ExceedMaxTokensPerStaker.selector); + launchpool.stake(2); + vm.stopPrank(); + + // Unstake half of the tokens + uint256 halfVTokens = launchpool.getTotalStakedVTokens() / 2; + vm.startPrank(alice); + launchpool.unstake(halfVTokens); + vm.stopPrank(); + + // Verify we're now under max + uint256 nativeStakeAfterUnstake = launchpool.getStakerNativeAmount( + alice + ); + assertLt( + nativeStakeAfterUnstake, + maxTokenPerStaker, + "Native stake should be less than maxTokenPerStaker after unstaking" + ); + + // Calculate how much we can stake to reach max again + uint256 remainingNative = maxTokenPerStaker - nativeStakeAfterUnstake; + nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 additionalStake = (remainingNative * + (10 ** vAsset.decimals())) / nativePerVToken; + + // Stake back to max + vm.startPrank(alice); + launchpool.stake(additionalStake); + vm.stopPrank(); + + // Verify we're at max again + uint256 finalNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + finalNativeStake, + maxTokenPerStaker, + 0.01e18, + "Final native stake should be approximately equal to maxTokenPerStaker" + ); + + // Try staking more, should fail again + vm.startPrank(alice); + vm.expectRevert(Launchpool.ExceedMaxTokensPerStaker.selector); + launchpool.stake(2); + vm.stopPrank(); + } + + function test_unstake_all_and_stake_again() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxTokenPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker with tokens + address alice = makeAddr("alice"); + uint256 totalVTokens = 2e3 * (10 ** vAsset.decimals()); // Mint plenty of tokens + vAsset.freeMintTo(alice, totalVTokens); + + // Stake half of max initially + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 halfMaxNative = maxTokenPerStaker / 2; + uint256 initialStake = (halfMaxNative * (10 ** vAsset.decimals())) / + nativePerVToken; + + vm.startPrank(alice); + vAsset.approve(address(launchpool), totalVTokens); + launchpool.stake(initialStake); + vm.stopPrank(); + + // Roll forward to accumulate some rewards + vm.roll(startBlock + 10); + + // Check rewards accumulated + uint256 rewardsBefore = launchpool.getClaimableProjectToken(alice); + assertTrue(rewardsBefore > 0, "Should have accumulated rewards"); + + // Get the withdrawable amount + uint256 aliceNativeStake = launchpool.getStakerNativeAmount(alice); + uint256 withdrawableVTokens = launchpool.getWithdrawableVTokens( + aliceNativeStake + ); + + // Unstake everything + vm.startPrank(alice); + launchpool.unstake(withdrawableVTokens); + vm.stopPrank(); + + // Verify completely unstaked + assertEq( + launchpool.getStakerNativeAmount(alice) - 1, // Its how EVM work + 0, + "Should have no native stake left" + ); + + // Roll forward again + vm.roll(startBlock + 20); + + // Stake to max + nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 maxStake = (maxTokenPerStaker * (10 ** vAsset.decimals())) / + nativePerVToken; + + vm.startPrank(alice); + launchpool.stake(maxStake); + vm.stopPrank(); + + // Verify at max + uint256 finalNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + finalNativeStake, + maxTokenPerStaker, + 0.01e18, + "Final native stake should be approximately equal to maxTokenPerStaker" + ); + + // Verify new rewards start accumulating from zero + uint256 rewardsAfter = launchpool.getClaimableProjectToken(alice); + assertEq(rewardsAfter, 0, "Rewards should reset after new stake"); + + // Roll forward more to see rewards accumulate again + vm.roll(startBlock + 30); + uint256 newRewards = launchpool.getClaimableProjectToken(alice); + assertTrue( + newRewards > 0, + "Should accumulate new rewards after staking again" + ); + } + + function test_unstake_with_changing_exrate_restake_to_max() public { + uint128[] memory changeBlocks = new uint128[](1); + uint256[] memory emissionRateChanges = new uint256[](1); + uint128 poolDurationBlocks = 70; + uint128 startBlock = uint128(block.number) + 1; + uint256 maxTokenPerStaker = 1e3 * (10 ** nativeAsset.decimals()); + uint128 endBlock = startBlock + poolDurationBlocks; + changeBlocks[0] = startBlock; + emissionRateChanges[0] = + (1e20 * (10 ** projectToken.decimals())) / + poolDurationBlocks; + + launchpool = new MockLaunchpool( + address(this), + address(projectToken), + address(vAsset), + address(nativeAsset), + startBlock, + endBlock, + maxTokenPerStaker, + changeBlocks, + emissionRateChanges + ); + + projectToken.transfer( + address(launchpool), + 1e20 * (10 ** projectToken.decimals()) + ); + + // Move to start block + vm.roll(startBlock); + + // Prepare staker with tokens + address alice = makeAddr("alice"); + uint256 totalVTokens = 3e3 * (10 ** vAsset.decimals()); // Mint plenty of tokens + vAsset.freeMintTo(alice, totalVTokens); + + // Stake to max initially + uint256 nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 initialStake = (maxTokenPerStaker * (10 ** vAsset.decimals())) / + nativePerVToken; + + vm.startPrank(alice); + vAsset.approve(address(launchpool), totalVTokens); + launchpool.stake(initialStake); + vm.stopPrank(); + + // Verify at max + uint256 initialNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + initialNativeStake, + maxTokenPerStaker, + 0.01e18, + "Initial native stake should be approximately equal to maxTokenPerStaker" + ); + + // Change exchange rate + xcmOracle.setExchangeRate(1.5e18); // 25% increase + + // Unstake half + uint256 halfVTokens = launchpool.getTotalStakedVTokens() / 2; + vm.startPrank(alice); + launchpool.unstake(halfVTokens); + vm.stopPrank(); + + // After unstaking half and with higher exchange rate, we should be significantly under max + uint256 midNativeStake = launchpool.getStakerNativeAmount(alice); + assertLt( + midNativeStake, + (maxTokenPerStaker * 2) / 3, // Should be notably less than 2/3 of max + "After unstaking with higher rate, should be well below max" + ); + + // Change exchange rate again + xcmOracle.setExchangeRate(1.8e18); // Another 20% increase + + // Calculate how much to stake to reach max again with new rate + uint256 remainingNative = maxTokenPerStaker - midNativeStake; + nativePerVToken = launchpool.exposed_getTokenByVTokenWithoutFee( + 10 ** vAsset.decimals() + ); + uint256 additionalStake = (remainingNative * + (10 ** vAsset.decimals())) / nativePerVToken; + + // Stake back to max + vm.startPrank(alice); + launchpool.stake(additionalStake); + vm.stopPrank(); + + // Verify we're at max again + uint256 finalNativeStake = launchpool.getStakerNativeAmount(alice); + assertApproxEqRel( + finalNativeStake, + maxTokenPerStaker, + 0.01e18, + "Final native stake should be approximately equal to maxTokenPerStaker" + ); + + // Try to stake more, should fail + vm.startPrank(alice); + vm.expectRevert(Launchpool.ExceedMaxTokensPerStaker.selector); + launchpool.stake(2); + vm.stopPrank(); + } +} diff --git a/test/MockXCMOracle/CustomDeployAddress.sol b/test/MockXCMOracle/CustomDeployAddress.sol new file mode 100644 index 0000000..fa2bb24 --- /dev/null +++ b/test/MockXCMOracle/CustomDeployAddress.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { ProjectHubUpgradeable } from "../../src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployProjectHubProxyCustomSender } from "../testutils/DeployProjectHubProxyCustomSender.sol"; +import { ProjectHubUpgradeable } from "../../src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { IXCMOracle } from "@src/interfaces/IXCMOracle.sol"; +import { DeployMockXCMOracle } from "../testutils/DeployMockXCMOracle.sol"; + +contract CustomDeployAddress is Test { + DeployMockXCMOracle mockXCMOracleDeployer = new DeployMockXCMOracle(); + address mockXCMOracleAddr; + + function setUp() public { + // Put MockXCMOracle at the hard-coded address of real on-chain XCMOracle + mockXCMOracleDeployer.deploy(12000, 10, 80000, 6); + mockXCMOracleAddr = mockXCMOracleDeployer.ORACLE_ONCHAIN_ADDRESS(); + } + + function test_mock_oracle_interactive() public view { + IXCMOracle.PoolInfo memory pool = IXCMOracle(mockXCMOracleAddr) + .tokenPool(0x0806); + assertTrue( + pool.assetAmount > 0 && pool.vAssetAmount > 0, + "Pool info should be set" + ); + } +} diff --git a/test/MockXCMOracle/OracleTest.t.sol b/test/MockXCMOracle/OracleTest.t.sol new file mode 100644 index 0000000..2d85b30 --- /dev/null +++ b/test/MockXCMOracle/OracleTest.t.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import "forge-std/Test.sol"; +import "@src/mocks/MockXCMOracle.sol"; +import "@src/mocks/MockERC20.sol"; + +contract MockXCMOracleTest is Test { + // MockXCMOracle public oracle; + // address mockTokenAddress = address(0x1); + // // Default constructor parameters + // uint256 initialRate = 15000; + // uint256 blockInterval = 50; + // uint256 apy = 80000; + // uint256 networkBlockTime = 6 seconds; + // function setUp() public { + // oracle = new MockXCMOracle( + // initialRate, + // blockInterval, + // apy, + // networkBlockTime + // ); + // } + // function test_initial_configuration() public { + // assertEq(oracle.baseExchangeRate(), initialRate); + // assertEq(oracle.blockInterval(), blockInterval); + // assertEq(oracle.lastUpdatedBlock(), block.number); + // } + // function test_get_current_exchange_rate() public { + // assertEq(oracle.getCurrentExchangeRate(), initialRate); + // assertEq(oracle.getExchangeRate(), initialRate); + // } + // function test_token_conversion() public { + // uint256 amount = 1000; + // assertEq( + // oracle.getVTokenByToken(mockTokenAddress, amount), + // amount / initialRate + // ); + // assertEq( + // oracle.getTokenByVToken(mockTokenAddress, amount), + // amount * initialRate + // ); + // } + // function test_set_exchange_rate() public { + // uint256 newRate = 20; + // oracle.setExchangeRate(newRate); + // assertEq(oracle.baseExchangeRate(), newRate); + // assertEq(oracle.getExchangeRate(), newRate); + // } + // function test_set_block_interval() public { + // uint256 newInterval = 100; + // oracle.setBlockInterval(newInterval); + // assertEq(oracle.blockInterval(), newInterval); + // assertEq(oracle.lastUpdatedBlock(), block.number); + // } + // function test_set_increment_amount() public { + // uint256 newIncrement = 2; + // oracle.setIncrementAmount(newIncrement); + // assertEq(oracle.incrementAmount(), newIncrement); + // assertEq(oracle.lastUpdatedBlock(), block.number); + // } + // function test_sync_exchange_rate() public { + // oracle.syncExchangeRate(); + // assertEq(oracle.lastUpdatedBlock(), block.number); + // } + // function test_rate_change_after_blocks() public { + // // Warp forward by 50 blocks to trigger one increment + // vm.roll(block.number + 50); + // uint256 expectedRate = initialRate + incrementAmount; + // assertEq(oracle.getCurrentExchangeRate(), expectedRate); + // // Check token conversions with new rate + // uint256 amount = 1000; + // assertEq( + // oracle.getVTokenByToken(mockTokenAddress, amount), + // amount / expectedRate + // ); + // assertEq( + // oracle.getTokenByVToken(mockTokenAddress, amount), + // amount * expectedRate + // ); + // } + // function test_multiple_block_intervals() public { + // // Warp forward by 105 blocks to trigger two increments + // vm.roll(block.number + 105); + // uint256 expectedRate = initialRate + (incrementAmount * 2); + // assertEq(oracle.getCurrentExchangeRate(), expectedRate); + // } + // function test_rate_update_after_set_exchange_rate() public { + // // Advance some blocks to have a non-zero increment + // vm.roll(block.number + 60); + // // Check that rate has increased + // assertEq( + // oracle.getCurrentExchangeRate(), + // initialRate + incrementAmount + // ); + // // Update the rate + // uint256 newRate = 25; + // oracle.setExchangeRate(newRate); + // // Verify that last block is updated + // assertEq(oracle.baseExchangeRate(), newRate); + // assertEq(oracle.lastUpdatedBlock(), block.number); + // // Move forward another block interval + // vm.roll(block.number + 50); + // // Check that the rate increases from the new base rate + // assertEq(oracle.getCurrentExchangeRate(), newRate + incrementAmount); + // } + // function test_fuzzing_rate_changes(uint8 blocks) public { + // vm.assume(blocks > 0); + // vm.roll(block.number + blocks); + // uint256 expectedIncrements = blocks / oracle.blockInterval(); + // uint256 expectedRate = oracle.baseExchangeRate() + + // (expectedIncrements * oracle.incrementAmount()); + // assertEq(oracle.getCurrentExchangeRate(), expectedRate); + // } + // function test_fuzzing_conversions(uint256 amount) public { + // vm.assume(amount > 0 && amount < type(uint256).max / initialRate); + // assertEq( + // oracle.getVTokenByToken(mockTokenAddress, amount), + // amount / initialRate + // ); + // assertEq( + // oracle.getTokenByVToken(mockTokenAddress, amount), + // amount * initialRate + // ); + // } +} diff --git a/test/ProjectHubUpgradeable/CreateLaunchpool.t.sol b/test/ProjectHubUpgradeable/CreateLaunchpool.t.sol new file mode 100644 index 0000000..11d16fa --- /dev/null +++ b/test/ProjectHubUpgradeable/CreateLaunchpool.t.sol @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { ProjectHubUpgradeable, LaunchpoolLibrary, ProjectLibrary, PoolTypeLib } from "../../src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployProjectHubProxyCustomSender } from "../testutils/DeployProjectHubProxyCustomSender.sol"; +import { IProjectHub } from "@src/interfaces/IProjectHub.sol"; +import { ILaunchpool } from "@src/interfaces/ILaunchpool.sol"; +import { DeployMockXCMOracle } from "../testutils/DeployMockXCMOracle.sol"; + +contract CreateLaunchpoolTest is Test { + MockERC20 public projectToken = new MockERC20("PROJECT", "PRO"); + uint256 projectTokenAmount = 1e7 * 10 ** projectToken.decimals(); + + MockERC20 vDOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 vGMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 vASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 vFIL = new MockERC20("Voucher FIL", "vFIL"); + + MockERC20 DOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 GMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 ASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 FIL = new MockERC20("Voucher FIL", "vFIL"); + + MockXCMOracle public mockXCMOracle = new MockXCMOracle(12000, 10, 80000, 6); + + DeployProjectHubProxyCustomSender public hubDeployScript; + DeployMockXCMOracle mockXCMOracleDeployer = new DeployMockXCMOracle(); + address[] vAssets; + address[] nativeAssets; + address public projectHubProxy; + uint256 public constant BLOCK_TIME = 6; + + constructor() { + vAssets.push(address(vDOT)); + vAssets.push(address(vGMLR)); + vAssets.push(address(vASTR)); + vAssets.push(address(vFIL)); + nativeAssets.push(address(DOT)); + nativeAssets.push(address(GMLR)); + nativeAssets.push(address(ASTR)); + nativeAssets.push(address(FIL)); + hubDeployScript = new DeployProjectHubProxyCustomSender( + vAssets, + nativeAssets, + address(this) + ); + } + + function setUp() public { + // Deploy and initialize ProjectHub + projectHubProxy = hubDeployScript.deployProjectHubProxy(); + + // Put MockXCMOracle at the hard-coded address of real on-chain XCMOracle + mockXCMOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function test_next_project_id() public { + // Arrange: + // 1. Get initial value of nextProjectId + uint nextProjectIdBefore = IProjectHub(projectHubProxy).nextProjectId(); + + // Act: + // 1. Create a project + IProjectHub(projectHubProxy).createProject(); + uint nextProjectIdAfter = IProjectHub(projectHubProxy).nextProjectId(); + + // Assert: + assertEq( + nextProjectIdBefore, + 1, + "Initial value of nextProjectId should be 1" + ); + assertEq(nextProjectIdAfter, nextProjectIdBefore + 1); + } + + function test_create_single_launchpool() public { + // Arrange: + // 1. Get initial value of nextPoolId + uint64 nextPoolIdBefore = IProjectHub(projectHubProxy).nextPoolId(); + + // 2. Create a project + IProjectHub(projectHubProxy).createProject(); + uint64 projectId = IProjectHub(projectHubProxy).nextProjectId() - 1; + uint128[] memory changeBlocks = new uint128[](2); + uint256[] memory emissionRateChanges = new uint256[](2); + uint128 startBlock = uint128(block.number + 1); + uint128 endBlock = uint128(block.number + 100); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + 1; + emissionRateChanges[0] = 1000 * 10 ** projectToken.decimals(); + emissionRateChanges[0] = 500 * 10 ** projectToken.decimals(); + + // 3. Prepare a set of params for launchpool creation + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(vDOT), + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 1000 * 1e18, + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + + // Act: + // 1. Create a launchpool for the project + projectToken.freeMint(projectTokenAmount); + projectToken.approve(projectHubProxy, projectTokenAmount); + uint64 poolId = ProjectHubUpgradeable(projectHubProxy).createLaunchpool( + params + ); + uint64 nextPoolIdAfter = IProjectHub(projectHubProxy).nextPoolId(); + + // Assert: + // 1. Assert nextPoolId increases + assertEq( + nextPoolIdBefore, + 1, + "Initial value of nextPoolId should be 1" + ); + assertEq(nextPoolIdAfter, nextPoolIdBefore + 1, "what the fuck"); + // 2. Assert pool info + ( + uint256 _poolId, + , + address _poolAddress, + uint64 _projectId + ) = ProjectHubUpgradeable(projectHubProxy).pools(nextPoolIdBefore); + assertEq(_projectId, projectId, "Wrong project Id"); + assertEq(_poolId, poolId, "Wrong pool Id"); + assertEq(ILaunchpool(_poolAddress).owner(), address(this)); + + // 3. Assert PoolCreated event emission + // Setup expected event + projectToken.freeMint(projectTokenAmount); + projectToken.approve(projectHubProxy, projectTokenAmount); + vm.expectEmit(true, true, true, false, projectHubProxy); + emit LaunchpoolLibrary.LaunchpoolCreated( + projectId, + PoolTypeLib.PoolType.LAUNCHPOOL, + poolId + 1, + address(projectToken), + address(vDOT), + address(0), // We dont' know this address yet, will match anything + startBlock, + endBlock + ); + + // Call createLaunchpool again to trigger event emission + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + + // 4. Assert project token balance in launchpool matches with that in params + uint256 launchpoolBalance = projectToken.balanceOf(_poolAddress); + assertEq( + launchpoolBalance, + params.projectTokenAmount, + "Project token balance in launchpool doesn't match with that in params" + ); + } + + function test_create_multiple_launchpools() public { + ("Address of test contract is: %s", address(this)); + // Arrange: + // 1. Get initial value of nextPoolId + uint256 poolCount = 86; + uint64 nextPoolIdBefore = IProjectHub(projectHubProxy).nextPoolId(); + + // 2. Create a project + IProjectHub(projectHubProxy).createProject(); + uint64 projectId = IProjectHub(projectHubProxy).nextProjectId() - 1; + + // 3. Fund just enough project tokens for all the pools that will be created soon + projectToken.freeMint(projectTokenAmount * poolCount); + projectToken.approve(projectHubProxy, projectTokenAmount * poolCount); + + // 4. Prepare a set of params for launchpool creation + uint128 startBlock = uint128(block.number + 1); + uint128 poolDurationBlocks = uint128(30 days / BLOCK_TIME); + uint128 endBlock = uint128(startBlock + poolDurationBlocks); + uint128[] memory changeBlocks = new uint128[](3); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + poolDurationBlocks / 2; + changeBlocks[2] = startBlock + (poolDurationBlocks * 3) / 4; + uint256[] memory emissionRateChanges = new uint256[](3); + emissionRateChanges[0] = 1000 * 10 ** projectToken.decimals(); + emissionRateChanges[1] = 500 * 10 ** projectToken.decimals(); + emissionRateChanges[2] = 200 * 10 ** projectToken.decimals(); + + bytes[] memory callPayloadBatch = new bytes[](poolCount); + for (uint256 i; i < poolCount; ++i) { + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(vDOT), + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 8686 * (10 ** vDOT.decimals()), + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + bytes memory callPayload = abi.encodeWithSelector( + ProjectHubUpgradeable(projectHubProxy) + .createLaunchpool + .selector, + params + ); + callPayloadBatch[i] = callPayload; + } + // Prepare selfMultiCall payload + bytes memory selfMulticallPayload = abi.encodeWithSignature( + "selfMultiCall(bytes[])", + callPayloadBatch + ); + + // Act: + // 1. Before the batch call, start recording logs + vm.recordLogs(); + // 2. Create multiple pools (execute batch transaction) + (bool success, bytes memory allReturnData) = address(projectHubProxy) + .call(selfMulticallPayload); + assertEq( + success, + true, + "Batch transaction to create multiple pools failed" + ); + // 3. Get all recorded logs + Vm.Log[] memory logs = vm.getRecordedLogs(); + + // Assert: + // Count PoolCreated events + bytes32 sigLaunchpoolCreated = keccak256( + "LaunchpoolCreated(uint64,uint8,uint64,address,address,address,uint128,uint128)" + ); + + // Debug information + console.log("Total logs emitted:", logs.length); + + uint256 poolCreatedEventCount = 0; + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == sigLaunchpoolCreated) { + ++poolCreatedEventCount; + // 1. Extract indexed parameters from topics + uint64 _projectId = uint64(uint256(logs[i].topics[1])); + uint8 _poolType = uint8(uint256(logs[i].topics[2])); + address _vAsset = address(uint160(uint256(logs[i].topics[3]))); + + // 2. Decode non-indexed parameters from data + ( + uint64 _poolId, + address _projectToken, + address _poolAddress, + uint128 _startBlock, + uint128 _endBlock + ) = abi.decode( + logs[i].data, + (uint64, address, address, uint128, uint128) + ); + assertEq(_projectId, projectId, "projectId mismatch"); + assertEq(_poolType, 0, "pool type mismatch"); + assertEq( + _projectToken, + address(projectToken), + "projectToken mismatch" + ); + assertEq(_vAsset, address(vDOT), "vAsset mismatch"); + assertEq(_startBlock, startBlock, "startBlock mismatch"); + assertEq(_endBlock, endBlock, "endBlock mismatch"); + assertEq( + _poolAddress, + IProjectHub(projectHubProxy).pools(_poolId).poolAddress, + "poolAddress mismatch" + ); + uint256 launchpoolBalance = projectToken.balanceOf( + _poolAddress + ); + assertEq( + launchpoolBalance, + projectTokenAmount, + "Project token balance in launchpool doesn't match with that in params" + ); + } + } + assertEq( + poolCreatedEventCount, + poolCount, + "Wrong number of PoolCreated events emitted" + ); + + bytes[] memory returnBytesArray = abi.decode(allReturnData, (bytes[])); + assertEq( + returnBytesArray.length, + poolCount, + "Wrong number of pools created" + ); + uint64[] memory allPoolIds = new uint64[](poolCount); + for (uint256 i; i < poolCount; ++i) { + uint64 poolId = abi.decode(returnBytesArray[i], (uint64)); + allPoolIds[i] = poolId; + } + + assertEq(allPoolIds.length, poolCount, "Wrong number of pools created"); + assertEq( + allPoolIds[0], + allPoolIds[poolCount - 1] - poolCount + 1, + "Pool created rapidly should have consecutive Ids" + ); + assertEq( + allPoolIds[0], + nextPoolIdBefore, + "Initial value of nextPoolId should be the first pool Id" + ); + uint64 nextPoolIdAfter = IProjectHub(projectHubProxy).nextPoolId(); + assertEq( + nextPoolIdAfter, + nextPoolIdBefore + poolCount, + "nextPoolId after creating multiple pools doesn't correctly reflect the amount of pool created" + ); + } + + function test_revert_create_launchpool_not_project_owner() public { + // Arrange: + // 1. Create a project + IProjectHub(projectHubProxy).createProject(); + uint64 projectId = IProjectHub(projectHubProxy).nextProjectId() - 1; + uint128[] memory changeBlocks = new uint128[](2); + uint256[] memory emissionRateChanges = new uint256[](2); + uint128 startBlock = uint128(block.number + 1); + uint128 endBlock = uint128(block.number + 100); + + // 2. Prepare a set of params for launchpool creation + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(vDOT), + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 1000 * 1e18, + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + + // Act: + // 1. Expect revert with custom error NotProjectOwner() + vm.expectRevert( + abi.encodeWithSelector(ProjectLibrary.NotProjectOwner.selector) + ); + + // 2. Impersonate a non-owner account, create a launchpool and see revert + vm.prank(address(1)); + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + } + + function test_revert_create_launchpool_not_registered_vAsset() public { + // Arrange: + // 1. Create a project + IProjectHub(projectHubProxy).createProject(); + uint64 projectId = IProjectHub(projectHubProxy).nextProjectId() - 1; + + // 2. Create a shitcoin for demonstration + MockERC20 shitcoin = new MockERC20("Shit coin", "SHIT"); + + // 3. Prepare a set of params for launchpool creation (insert shitcoin into params) + uint128[] memory changeBlocks = new uint128[](2); + uint256[] memory emissionRateChanges = new uint256[](2); + uint128 startBlock = uint128(block.number + 1); + uint128 endBlock = uint128(block.number + 100); + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(shitcoin), // put shitcoin here + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 1000 * 1e18, + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + + // Act: + // 1.expect revert with custom error NotAcceptedVAsset() + vm.expectRevert(ProjectHubUpgradeable.NotAcceptedVAsset.selector); + //2. Create a launchpool with a non-accepted vAsset (shitcoin) + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + } + + function test_revert_create_launchpool_project_not_found() public { + // Arrange: + // 1. Retrieve a non-existent project ID + uint64 projectId = ProjectHubUpgradeable(projectHubProxy) + .nextProjectId(); + + // 2. Prepare a set of params for launchpool creation + uint128 startBlock = uint128(block.number + 1); + uint128 endBlock = uint128(block.number + 100); + uint128[] memory changeBlocks = new uint128[](2); + uint256[] memory emissionRateChanges = new uint256[](2); + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(vDOT), + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 1000 * 1e18, + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + // 3. Expect revert with custom error ProjectNotFound() + vm.expectRevert(ProjectLibrary.ProjectNotFound.selector); + + // Act & Assert: + // 1. Call createLaunchpool with non-existent project ID and wait for revert + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + } + + function test_revert_create_launchpool_not_enough_project_token_allowance() + public + { + // Arrange: + // 1. Create a project + IProjectHub(projectHubProxy).createProject(); + uint64 projectId = IProjectHub(projectHubProxy).nextProjectId() - 1; + + // 2. Prepare a set of params for launchpool creation + uint128 startBlock = uint128(block.number + 1); + uint128 endBlock = uint128(block.number + 100); + uint128[] memory changeBlocks = new uint128[](2); + uint256[] memory emissionRateChanges = new uint256[](2); + changeBlocks[0] = startBlock; + changeBlocks[1] = startBlock + 1; + emissionRateChanges[0] = 1000 * 10 ** projectToken.decimals(); + emissionRateChanges[1] = 500 * 10 ** projectToken.decimals(); + + LaunchpoolLibrary.LaunchpoolCreationParams + memory params = LaunchpoolLibrary.LaunchpoolCreationParams({ + projectId: uint64(projectId), + projectTokenAmount: projectTokenAmount, + projectToken: address(projectToken), + vAsset: address(vDOT), + startBlock: startBlock, + endBlock: endBlock, + maxVTokensPerStaker: 1000 * 1e18, + changeBlocks: changeBlocks, + emissionRateChanges: emissionRateChanges + }); + + // 3. Set project token allowance to 0 + projectToken.approve(projectHubProxy, 0); + + // Act: + // 1. Call createLaunchpool and expect revert + vm.expectRevert( + abi.encodeWithSignature( + "ERC20InsufficientAllowance(address,uint256,uint256)", + projectHubProxy, + 0, + projectTokenAmount + ) + ); + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + + // 2. Set project token allowance to be equal to project token amount + projectToken.freeMint(projectTokenAmount); // mint just to make sure + projectToken.approve(projectHubProxy, projectTokenAmount); + + // 3 Use tokens so that the balance drop below allowance + uint256 initialBalance = projectToken.balanceOf(address(this)); + projectToken.transfer( + address(1), + initialBalance - projectTokenAmount + 1 + ); + uint256 finalBalance = projectToken.balanceOf(address(this)); + console.log("Balance:", finalBalance); + console.log("Required:", projectTokenAmount); + require( + finalBalance < projectTokenAmount, + "Balance should be insufficient" + ); + + // 4. Call createLaunchpool and expect revert once again + vm.expectRevert( + abi.encodeWithSignature( + "ERC20InsufficientBalance(address,uint256,uint256)", + address(this), + finalBalance, + projectTokenAmount + ) + ); + ProjectHubUpgradeable(projectHubProxy).createLaunchpool(params); + } +} diff --git a/test/ProjectHubUpgradeable/GeneralSetters.t.sol b/test/ProjectHubUpgradeable/GeneralSetters.t.sol new file mode 100644 index 0000000..37d483a --- /dev/null +++ b/test/ProjectHubUpgradeable/GeneralSetters.t.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +import "forge-std/Test.sol"; +import { ProjectHubUpgradeable, PoolTypeLib } from "@src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployProjectHubProxyCustomSender } from "../testutils/DeployProjectHubProxyCustomSender.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { ILaunchpool } from "@src/interfaces/ILaunchpool.sol"; +import { DeployMockXCMOracle } from "../testutils/DeployMockXCMOracle.sol"; +import { console } from "forge-std/console.sol"; + +contract GeneralSetters is Test { + MockERC20 public projectToken; + MockERC20 public vAsset; + + MockERC20 vDOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 vGMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 vASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 vFIL = new MockERC20("Voucher FIL", "vFIL"); + + MockERC20 DOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 GMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 ASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 FIL = new MockERC20("Voucher FIL", "vFIL"); + + MockXCMOracle public mockXCMOracle = new MockXCMOracle(12000, 10, 80000, 6); + + DeployProjectHubProxyCustomSender public hubDeployScript; + DeployMockXCMOracle public mockXCMOracleDeployer = + new DeployMockXCMOracle(); + address[] vAssets; + address[] nativeAssets; + address public projectHubProxy; + uint256 public constant BLOCK_TIME = 6; + + constructor() { + vAssets.push(address(vDOT)); + vAssets.push(address(vGMLR)); + vAssets.push(address(vASTR)); + vAssets.push(address(vFIL)); + nativeAssets.push(address(DOT)); + nativeAssets.push(address(GMLR)); + nativeAssets.push(address(ASTR)); + nativeAssets.push(address(FIL)); + hubDeployScript = new DeployProjectHubProxyCustomSender( + vAssets, + nativeAssets, + address(this) + ); + } + + function setUp() public { + projectToken = new MockERC20("PROJECT", "PRO"); + vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + + // Deploy and initialize ProjectHub + projectHubProxy = hubDeployScript.deployProjectHubProxy(); + + // Put MockXCMOracle at the hard-coded address of real on-chain XCMOracle + mockXCMOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function test_set_native_asset_for_vAsset() public { + // Arrange: + // Check owner permission beforehand + address owner = ProjectHubUpgradeable(projectHubProxy).owner(); + console.log("this address: ", address(this)); + assert(owner == address(this)); + // Deploy new asset pair + MockERC20 newVAsset = new MockERC20("New Voucher Token", "vNew"); + MockERC20 newNativeAsset = new MockERC20("New Native", "New"); + + // Act: + // Verify initial state is not set + assertEq( + ProjectHubUpgradeable(projectHubProxy).vAssetToNativeAsset( + address(newVAsset) + ), + address(0) + ); + + // Set vAsset2 as accepted vAsset + ProjectHubUpgradeable(projectHubProxy).setNativeAssetForVAsset( + address(newVAsset), + address(newNativeAsset) + ); + + // Assert: + address nativeAssetAddress = ProjectHubUpgradeable(projectHubProxy) + .vAssetToNativeAsset(address(newVAsset)); + assertEq( + nativeAssetAddress, + address(newNativeAsset), + "Native asset for vAsset should be set" + ); + } + + function test_revert_set_accepted_vAsset_not_owner() public { + // Arrange: + // Check owner permission beforehand + assert(ProjectHubUpgradeable(projectHubProxy).owner() == address(this)); + // Deploy new asset pair + MockERC20 newVAsset = new MockERC20("New Voucher Token", "vNew"); + MockERC20 newNativeAsset = new MockERC20("New Native", "New"); + + // Act & Assert: + // Set vAsset2 as accepted vAsset + address alice = vm.addr(0x868); + vm.expectRevert( + abi.encodeWithSelector( + OwnableUpgradeable.OwnableUnauthorizedAccount.selector, + alice + ) + ); + vm.prank(alice); + ProjectHubUpgradeable(projectHubProxy).setNativeAssetForVAsset( + address(newVAsset), + address(newNativeAsset) + ); + } + + function test_set_multiple_accepted_vAssets() public { + // Arrange & Act: + // Check owner permission beforehand + assert(ProjectHubUpgradeable(projectHubProxy).owner() == address(this)); + // Deploy multiple mock vAssets and set them as accepted vAssets in projectHub contract + uint256 vAssetsCount = 86; + MockERC20[] memory additionalVAssets = new MockERC20[](vAssetsCount); + MockERC20[] memory additionalNativeAssets = new MockERC20[]( + vAssetsCount + ); + for (uint256 i; i < vAssetsCount; ++i) { + additionalVAssets[i] = new MockERC20( + string(abi.encodePacked("Voucher Imaginary ", i)), + string(abi.encodePacked("vImaginary", i)) + ); + additionalNativeAssets[i] = new MockERC20( + string(abi.encodePacked("Native Asset ", i)), + string(abi.encodePacked("Native ", i)) + ); + ProjectHubUpgradeable(projectHubProxy).setNativeAssetForVAsset( + address(additionalVAssets[i]), + address(additionalNativeAssets[i]) + ); + } + + // Assert: + for (uint256 i; i < vAssetsCount; ++i) { + address nativeAssetAddress = ProjectHubUpgradeable(projectHubProxy) + .vAssetToNativeAsset(address(additionalVAssets[i])); + assertEq( + nativeAssetAddress, + address(additionalNativeAssets[i]), + string(abi.encodePacked("vAsset ", i, "should be accepted")) + ); + } + } +} diff --git a/test/ProjectHubUpgradeable/GeneralState.t.sol b/test/ProjectHubUpgradeable/GeneralState.t.sol new file mode 100644 index 0000000..d7378d0 --- /dev/null +++ b/test/ProjectHubUpgradeable/GeneralState.t.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import { ProjectHubUpgradeable } from "../../src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { console } from "forge-std/console.sol"; +import { DeployProjectHubProxyCustomSender } from "../testutils/DeployProjectHubProxyCustomSender.sol"; +import { ProjectHubUpgradeable } from "../../src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { DeployMockXCMOracle } from "../testutils/DeployMockXCMOracle.sol"; + +contract GeneralStateTest is Test { + MockERC20 public projectToken; + MockERC20 public vAsset; + + MockERC20 vDOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 vGMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 vASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 vFIL = new MockERC20("Voucher FIL", "vFIL"); + + MockERC20 DOT = new MockERC20("Voucher DOT", "vDOT"); + MockERC20 GMLR = new MockERC20("Voucher GMLR", "vGMLR"); + MockERC20 ASTR = new MockERC20("Voucher ASTR", "vASTR"); + MockERC20 FIL = new MockERC20("Voucher FIL", "vFIL"); + + MockXCMOracle public mockXCMOracle = new MockXCMOracle(12000, 10, 80000, 6); + + DeployProjectHubProxyCustomSender public hubDeployScript; + DeployMockXCMOracle public mockXCMOracleDeployer = + new DeployMockXCMOracle(); + address[] vAssets; + address[] nativeAssets; + uint64 public projectId; + address public projectHubProxy; + + constructor() { + vAssets.push(address(vDOT)); + vAssets.push(address(vGMLR)); + vAssets.push(address(vASTR)); + vAssets.push(address(vFIL)); + nativeAssets.push(address(DOT)); + nativeAssets.push(address(GMLR)); + nativeAssets.push(address(ASTR)); + nativeAssets.push(address(FIL)); + hubDeployScript = new DeployProjectHubProxyCustomSender( + vAssets, + nativeAssets, + address(this) + ); + } + + function setUp() public { + projectToken = new MockERC20("PROJECT", "PRO"); + vAsset = new MockERC20("Voucher Imaginary", "vImaginary"); + + // Deploy and initialize ProjectHub + projectHubProxy = hubDeployScript.deployProjectHubProxy(); + projectId = 1; // First project ID + + // Put MockXCMOracle at the hard-coded address of real on-chain XCMOracle + mockXCMOracleDeployer.deploy(12000, 10, 80000, 6); + } + + function test_initialized_acceptedVAssets() public view { + for (uint256 i; i < vAssets.length; ++i) { + address nativeAssetAddress = ProjectHubUpgradeable(projectHubProxy) + .vAssetToNativeAsset(vAssets[i]); + assertEq( + nativeAssetAddress, + nativeAssets[i], + string.concat( + "vAsset ", + vm.toString(vAssets[i]), + " should be accepted if project hub had been initialized" + ) + ); + } + } + + function test_initialized_owner() public { + bytes memory callPayload = abi.encodeWithSignature("owner()"); + (bool success, bytes memory returnData) = projectHubProxy.call( + callPayload + ); + assert(success == true); + address projectHubOwner = abi.decode(returnData, (address)); + assertEq( + projectHubOwner, + address(this), + "Owner should be the deployer of the project hub" + ); + } + + function test_initialized_nextPoolId() public { + bytes memory callPayload = abi.encodeWithSignature("nextPoolId()"); + (bool success, bytes memory returnData) = projectHubProxy.call( + callPayload + ); + assert(success == true); + uint64 nextPoolId = abi.decode(returnData, (uint64)); + assertEq(nextPoolId, 1, "Initial value of nextPoolId should be 1"); + } + + function test_intialized_nextProjectId() public { + bytes memory callPayload = abi.encodeWithSignature("nextProjectId()"); + (bool success, bytes memory returnData) = projectHubProxy.call( + callPayload + ); + assert(success == true); + uint64 nextProjectId = abi.decode(returnData, (uint64)); + assertEq( + nextProjectId, + 1, + "Initial value of nextProjectId should be 1" + ); + } +} diff --git a/test/simulation/launchpoolStateMachine.js b/test/simulation/launchpoolStateMachine.js new file mode 100644 index 0000000..511e960 --- /dev/null +++ b/test/simulation/launchpoolStateMachine.js @@ -0,0 +1,272 @@ +/** + * @fileoverview State machine simulation for launchpool contract debugging + * + * @description + * This module implements a prototype state machine that simulates the state transitions + * of a launchpool contract. It is used for debugging purposes in a controlled environment. + * The simulation handles staking mechanics, emission rate changes, and reward calculations. + * + * Core Components: + * - Exchange rate tracking + * - Block-based timing system + * - Staker management + * - Emission rate scheduling + * + */ + +// State variables +let cumulativeExchangeRate = 0n; +let startBlock = BigInt(100n); +const BLOCK_TIME_SECONDS = 6; +let poolDurationBlocks = BigInt((14 * 86400) / BLOCK_TIME_SECONDS); +let endBlock = startBlock + poolDurationBlocks; +let tickBlock = BigInt(startBlock); +let ownerShareOfInterest = 70n; // 70% default +let maxVAssetPerStaker = BigInt(1000 * 1e18); +let maxStakers = 0n; +let currentBlock = 0n; + +let totalStaked = 0n; + +// Block processing state +let lastProcessedChangeBlockIndex = 0; + +// Addresses +let platformAdminAddress = "defrost"; +// let projectToken = projectToken; +// let acceptedVAsset = acceptedVAsset; + +// Rate changes +let changeBlocks = [ + startBlock, + startBlock + poolDurationBlocks / 3n, + startBlock + (poolDurationBlocks * 3n) / 4n, +]; + +// Initialize emission rate changes +let emissionRateChanges = new Map(); +emissionRateChanges.set(changeBlocks[0], BigInt(10000 * 1e18)); +emissionRateChanges.set(changeBlocks[1], BigInt(1000 * 1e18)); +emissionRateChanges.set(changeBlocks[2], BigInt(900 * 1e18)); + +// Stakers mapping +let stakers = new Map(); + +function setCurrentBlock(_currentBlock) { + currentBlock = _currentBlock; +} + +function createStaker() { + return { + vAssetAmount: 0n, + nativeTokenAmount: 0n, + claimOffset: 0n, + }; +} + +// Helper method to get staker info +function getStaker(address) { + if (!stakers.has(address)) { + stakers.set(address, createStaker()); + } + return stakers.get(address); +} + +function _getPendingExchangeRate() { + // Early return if no stakes + if (totalStaked === 0n) { + return 0n; + } + + let periodStartBlock = tickBlock; + let periodEndBlock; + let accumulatedIncrease = 0n; + + // Process all change blocks + let i = lastProcessedChangeBlockIndex; + for (; i < changeBlocks.length; i++) { + periodEndBlock = changeBlocks[i]; + + // Break if we've reached a future change block + if (periodEndBlock >= currentBlock) { + break; + } + + if (periodEndBlock <= periodStartBlock) { + continue; + } + + // Calculate blocks elapsed in this period + const tickBlockDelta = getTickBlockDelta( + periodStartBlock, + periodEndBlock, + endBlock, + ); + + // Get emission rate for this period + const emissionRate = + i === 0 + ? emissionRateChanges[changeBlocks[0]] + : emissionRateChanges[changeBlocks[i - 1]]; + + // Add to accumulated increase + accumulatedIncrease += + (BigInt(emissionRate) * BigInt(tickBlockDelta)) / totalStaked; + + // Move start block forward + periodStartBlock = periodEndBlock; + } + + // Process final period + const finalDelta = getTickBlockDelta( + periodStartBlock, + currentBlock, + endBlock, + ); + + // Get final emission rate + const finalEmissionRate = + // periodEndBlock <= currentBlock + // ? emissionRateChanges.get(periodEndBlock) // Rate for period that started at periodEndBlock + // : emissionRateChanges.get(changeBlocks[i - 1]); // Rate after last processed change block + BigInt(getEmissionRate()); + + // Add final period increase + accumulatedIncrease += + (BigInt(finalEmissionRate) * BigInt(finalDelta)) / totalStaked; + + return accumulatedIncrease; +} + +function getEmissionRate() { + if (currentBlock >= endBlock) { + return 0n; + } + + let emissionRate = 0n; + let len = changeBlocks.length; + for (let i = lastProcessedChangeBlockIndex; i < len; ++i) { + if (currentBlock < changeBlocks[i]) { + break; + } + emissionRate = emissionRateChanges.get(changeBlocks[i]); + } + return emissionRate; +} + +function getTickBlockDelta(from, to, endBlock) { + if (to < endBlock) { + return BigInt(to - from); + } else if (from >= endBlock) { + return 0n; + } + return BigInt(endBlock - from); +} + +function stake(sender, amount) { + // Input validation + if (amount === 0n) { + throw new Error("ZeroAmountNotAllowed"); + } + + if (amount > maxVAssetPerStaker) { + throw new Error("ExceedsMaximumAllowedStakePerUser"); + } + + // Get or create investor record + let investor = stakers.get(sender) || { + vAssetAmount: 0n, + nativeTokenAmount: 0n, + claimOffset: 0n, + }; + + _tick(); + + // Handle existing stake rewards + if (investor.vAssetAmount > 0n) { + const claimableProjectTokenAmount = + investor.vAssetAmount * cumulativeExchangeRate - + investor.claimOffset; + + if (claimableProjectTokenAmount > 0n) { + // Transfer project tokens to sender + // await projectToken.transfer(sender, claimableProjectTokenAmount); + } + } + + // Update investor state + investor.vAssetAmount += amount; + + // Transfer staked tokens from sender + totalStaked += amount; + + // TODO: Implement native amount increase here + + // Update claim offset + investor.claimOffset = investor.vAssetAmount * cumulativeExchangeRate; + + // Save updated investor state + stakers.set(sender, investor); +} + +function _tick() { + if (currentBlock <= tickBlock) { + return; + } + + if (totalStaked == 0) { + tickBlock = currentBlock; + _updateLastProcessedIndex(); + return; + } + + cumulativeExchangeRate += _getPendingExchangeRate(); + tickBlock = currentBlock; + _updateLastProcessedIndex(); +} + +function _updateLastProcessedIndex() { + let len = changeBlocks.length; + for (let i = lastProcessedChangeBlockIndex; i < len; i++) { + if (changeBlocks[i] > tickBlock) { + break; + } + lastProcessedChangeBlockIndex = i; + } +} + +function main() { + stakers.set("alice", { + vAssetAmount: 0n, + nativeTokenAmount: 0n, + claimOffset: 0n, + }); + stakers.set("bob", { + vAssetAmount: 0n, + nativeTokenAmount: 0n, + claimOffset: 0n, + }); + + const aliceStakeBlock = startBlock + 50n; + setCurrentBlock(aliceStakeBlock); + console.log("Alice stakes at block: ", aliceStakeBlock); + aliceStake = 750n * BigInt(1e18); + stake("alice", aliceStake); + console.log( + "Adjusted cumulative exchange after alice stake: ", + cumulativeExchangeRate, + ); + + console.log("changeBlocks[i] - 1 is: ", changeBlocks[1] - 1n); + setCurrentBlock(changeBlocks[1] - 1n); + bobStake = 300n * BigInt(1e18); + stake("bob", bobStake); + console.log( + "Adjusted cumulative exchange after bob stake: ", + cumulativeExchangeRate, + ); + + setCurrentBlock(endBlock); +} + +main(); diff --git a/test/testutils/DeployMockXCMOracle.sol b/test/testutils/DeployMockXCMOracle.sol new file mode 100644 index 0000000..7c22064 --- /dev/null +++ b/test/testutils/DeployMockXCMOracle.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import "forge-std/Test.sol"; +import { Upgrades } from "@openzeppelin-foundry-upgrades/Upgrades.sol"; +import { ProjectHubUpgradeable } from "@src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { MockXCMOracle } from "@src/mocks/MockXCMOracle.sol"; +import { Context } from "@openzeppelin/contracts/access/Ownable.sol"; +import { console } from "forge-std/console.sol"; +import { Script } from "forge-std/Script.sol"; + +contract DeployMockXCMOracle is Script, Test { + address public constant ORACLE_ONCHAIN_ADDRESS = + 0xEF81930Aa8ed07C17948B2E26b7bfAF20144eF2a; + + function deploy( + uint256 _baseExchangeRate, + uint256 _blockInterval, + uint256 _apy, + uint256 _networkBlockTime + ) public returns (address) { + deployCodeTo( + "MockXCMOracle", + abi.encode( + _baseExchangeRate, + _blockInterval, + _apy, + _networkBlockTime + ), + ORACLE_ONCHAIN_ADDRESS + ); + + return ORACLE_ONCHAIN_ADDRESS; + } +} diff --git a/test/testutils/DeployProjectHub.sol b/test/testutils/DeployProjectHub.sol new file mode 100644 index 0000000..8d6d2f6 --- /dev/null +++ b/test/testutils/DeployProjectHub.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +import { Upgrades } from "@openzeppelin-foundry-upgrades/Upgrades.sol"; +import { ProjectHubUpgradeable } from "@src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { Context } from "@openzeppelin/contracts/access/Ownable.sol"; +import { console } from "forge-std/console.sol"; +import { Script } from "forge-std/Script.sol"; + +contract DeployProjectHub is Context, Script { + address[] public vAssets; + address[] public nativeAssets; + + function run(address[] calldata _vAssets) external { + setVAssets(_vAssets); + deployProjectHub(); + } + + function setVAssets(address[] memory _vAssets) public { + vAssets = _vAssets; + } + + function setNativeAsets(address[] memory _nativeAssets) public { + nativeAssets = _nativeAssets; + } + + /** + * @notice for testing purpose only + */ + function deployProjectHub() public returns (address projectHubAddress) { + projectHubAddress = address(new ProjectHubUpgradeable()); + ProjectHubUpgradeable(projectHubAddress).initialize( + 0xEF81930Aa8ed07C17948B2E26b7bfAF20144eF2a, + _msgSender(), + vAssets, + nativeAssets + ); + + console.log( + "Deployed ProjectHubUpgradable at address: %s", + projectHubAddress + ); + return projectHubAddress; + } + + function run() public { + deployProjectHub(); + } +} diff --git a/test/testutils/DeployProjectHubProxy.sol b/test/testutils/DeployProjectHubProxy.sol new file mode 100644 index 0000000..b907baa --- /dev/null +++ b/test/testutils/DeployProjectHubProxy.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +import { Upgrades } from "@openzeppelin-foundry-upgrades/Upgrades.sol"; +import { Options } from "@openzeppelin-foundry-upgrades/Options.sol"; +import { ProjectHubUpgradeable } from "@src/upgradeable/v1/ProjectHubUpgradeable.sol"; +import { Context } from "@openzeppelin/contracts/access/Ownable.sol"; +import { console } from "forge-std/console.sol"; +import { Script } from "forge-std/Script.sol"; +import { DeployMockXCMOracle } from "./DeployMockXCMOracle.sol"; + +contract DeployProjectHubProxy is Context, Script { + address[] public vAssets; + address[] public nativeAssets; + DeployMockXCMOracle public oracleDeployer = new DeployMockXCMOracle(); + + function setVAssets(address[] memory _vAssets) public { + vAssets = _vAssets; + } + + function setNativeAssets(address[] memory _nativeAssets) public { + nativeAssets = _nativeAssets; + } + + function deployProjectHubProxy() public returns (address proxyAddress) { + vm.startBroadcast(); + address oracleAddr = oracleDeployer.deploy(1e18, 10, 80000, 6); + + Options memory opt; + opt.unsafeAllow = "external-library-linking"; + proxyAddress = Upgrades.deployTransparentProxy( + "ProjectHubUpgradeable.sol:ProjectHubUpgradeable", + _msgSender(), + abi.encodeCall( + ProjectHubUpgradeable.initialize, + (oracleAddr, _msgSender(), vAssets, nativeAssets) + ), + opt + ); + + console.log( + "Deployed UUPS ProjectHubUpgradable proxy at address: %s", + proxyAddress + ); + vm.stopBroadcast(); + return proxyAddress; + } + + function run() public { + deployProjectHubProxy(); + } +} diff --git a/test/testutils/DeployProjectHubProxyCustomSender.sol b/test/testutils/DeployProjectHubProxyCustomSender.sol new file mode 100644 index 0000000..9b4c39a --- /dev/null +++ b/test/testutils/DeployProjectHubProxyCustomSender.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { DeployProjectHubProxy } from "./DeployProjectHubProxy.sol"; + +contract DeployProjectHubProxyCustomSender is DeployProjectHubProxy { + address sender; + + constructor( + address[] memory _vAssets, + address[] memory _nativeAssets, + address _sender + ) DeployProjectHubProxy() { + setSender(_sender); + setVAssets(_vAssets); + setNativeAssets(_nativeAssets); + } + + function setSender(address _sender) public { + sender = _sender; + } + + function _msgSender() internal view override returns (address) { + return sender; + } +} diff --git a/test/testutils/SetupStakers.sol b/test/testutils/SetupStakers.sol new file mode 100644 index 0000000..cbc8521 --- /dev/null +++ b/test/testutils/SetupStakers.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.26; + +import "forge-std/Test.sol"; +import { MockERC20 } from "@src/mocks/MockERC20.sol"; + +// import { MockLaunchpool } + +contract SetupStakers is Test { + function createAndApprove( + uint256 stakerCount, + address launchpoolAddr, + address vAsset + ) public returns (address[] memory) { + // Generate a random salt for the stakers + uint256 salt = uint256( + keccak256( + abi.encodePacked( + block.timestamp, + block.prevrandao, + stakerCount, + msg.sender, + tx.origin, + block.coinbase + ) + ) + ); + address[] memory stakers = new address[](stakerCount); + for (uint i; i < stakerCount; i++) { + address newStaker = makeAddr( + string(abi.encodePacked("staker ", i, salt)) + ); + stakers[i] = newStaker; + MockERC20(vAsset).freeMintTo(newStaker, 1e55); + vm.prank(newStaker); + MockERC20(vAsset).approve(launchpoolAddr, 1e55); + } + return stakers; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0e79616 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +}