From 3dace31dbee9797e1d90f425a86d73a6e917e3fa Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Tue, 22 Oct 2024 11:09:42 -0400 Subject: [PATCH 1/3] Install lint and pretty tools and configs --- .eslintrc.json | 43 + .prettierignore | 1 + .prettierrc | 10 + package-lock.json | 2111 ++++++++++++++++++++++++++++----------------- package.json | 15 +- 5 files changed, 1398 insertions(+), 782 deletions(-) create mode 100644 .eslintrc.json create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..ed6d7f02 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,43 @@ +{ + "env": { + "es2021": true + }, + "extends": ["plugin:import/recommended", "airbnb-typescript/base", "prettier"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + // required for "type-aware linting" + "project": ["./tsconfig.json"], + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["import", "@typescript-eslint"], + "settings": { + // resolves imports without file extensions for listed extensions + "import/resolver": { + "node": { + "extensions": [".ts"] + } + } + }, + "rules": { + "comma-dangle": "off", + "@typescript-eslint/comma-dangle": "off", + "indent": "off", + "@typescript-eslint/indent": "off", + "import/order": [ + "error", + { + "alphabetize": { + "order": "asc", + "caseInsensitive": false + } + } + ], + // var rules + "no-use-before-define": "off", + "@typescript-eslint/no-use-before-define": "error", + "@typescript-eslint/no-unused-vars": "warn", + // class rules + "@typescript-eslint/lines-between-class-members": "off" + } +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..5d5689b3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +deployments/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..90a9a138 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "printWidth": 100, + "endOfLine": "auto", + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "semi": true, + "arrowParens": "avoid", + "singleAttributePerLine": true +} diff --git a/package-lock.json b/package-lock.json index 7aa16857..5d05df06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,16 +8,25 @@ "name": "@fractal-framework/fractal-contracts", "version": "1.2.16", "license": "MIT", - "devDependencies": { + "dependencies": { "@gnosis.pm/zodiac": "^1.1.4", + "@nomicfoundation/hardhat-ethers": "^3.0.5", "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts-upgradeable": "^4.5.0", "@prb/math": "^4.0.3", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "chai": "^4.2.0", "dotenv": "^16.4.5", + "eslint": "^8.22.0", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", "hardhat": "^2.22.2", "hardhat-dependency-compiler": "^1.1.4", "hardhat-deploy": "^0.12.2", + "prettier": "^3.3.3", "solidity-docgen": "^0.6.0-beta.36" } }, @@ -25,14 +34,12 @@ "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "dev": true, "peer": true }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -41,11 +48,82 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/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==" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "dev": true, "peer": true, "bin": { "rlp": "bin/rlp" @@ -58,7 +136,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", - "dev": true, "peer": true, "dependencies": { "@ethereumjs/rlp": "^4.0.1", @@ -73,7 +150,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "1.3.3" @@ -86,7 +162,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, "peer": true, "engines": { "node": ">= 16" @@ -99,7 +174,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", - "dev": true, "peer": true, "dependencies": { "@noble/curves": "1.3.0", @@ -112,7 +186,6 @@ "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", @@ -139,7 +212,6 @@ "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", @@ -164,7 +236,6 @@ "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", @@ -187,7 +258,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, "funding": [ { "type": "individual", @@ -210,7 +280,6 @@ "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", @@ -229,7 +298,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, "funding": [ { "type": "individual", @@ -249,7 +317,6 @@ "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", @@ -270,7 +337,6 @@ "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", @@ -289,7 +355,6 @@ "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", @@ -308,7 +373,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, "funding": [ { "type": "individual", @@ -336,7 +400,6 @@ "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", @@ -363,7 +426,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, "funding": [ { "type": "individual", @@ -393,7 +455,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, "funding": [ { "type": "individual", @@ -423,14 +484,12 @@ "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" }, "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", @@ -450,7 +509,6 @@ "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", @@ -466,7 +524,6 @@ "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", @@ -485,7 +542,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, "funding": [ { "type": "individual", @@ -505,7 +561,6 @@ "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", @@ -524,7 +579,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, "funding": [ { "type": "individual", @@ -562,7 +616,6 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, "engines": { "node": ">=8.3.0" }, @@ -583,7 +636,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "dev": true, "funding": [ { "type": "individual", @@ -603,7 +655,6 @@ "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", @@ -623,7 +674,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, "funding": [ { "type": "individual", @@ -644,7 +694,6 @@ "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", @@ -668,7 +717,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, "funding": [ { "type": "individual", @@ -692,7 +740,6 @@ "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", @@ -713,7 +760,6 @@ "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", @@ -740,7 +786,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, "funding": [ { "type": "individual", @@ -761,7 +806,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, "funding": [ { "type": "individual", @@ -794,7 +838,6 @@ "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", @@ -817,7 +860,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "dev": true, "funding": [ { "type": "individual", @@ -840,7 +882,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, "engines": { "node": ">=14" } @@ -848,14 +889,12 @@ "node_modules/@gnosis.pm/mock-contract": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@gnosis.pm/mock-contract/-/mock-contract-4.0.0.tgz", - "integrity": "sha512-SkRq2KwPx6vo0LAjSc8JhgQstrQFXRyn2yqquIfub7r2WHi5nUbF8beeSSXsd36hvBcQxQfmOIYNYRpj9JOhrQ==", - "dev": true + "integrity": "sha512-SkRq2KwPx6vo0LAjSc8JhgQstrQFXRyn2yqquIfub7r2WHi5nUbF8beeSSXsd36hvBcQxQfmOIYNYRpj9JOhrQ==" }, "node_modules/@gnosis.pm/safe-contracts": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-contracts/-/safe-contracts-1.3.0.tgz", "integrity": "sha512-1p+1HwGvxGUVzVkFjNzglwHrLNA67U/axP0Ct85FzzH8yhGJb4t9jDjPYocVMzLorDoWAfKicGy1akPY9jXRVw==", - "dev": true, "peerDependencies": { "ethers": "^5.1.4" } @@ -864,7 +903,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@gnosis.pm/zodiac/-/zodiac-1.1.4.tgz", "integrity": "sha512-qELBXyD6lf3S0hcKnsiy4K5ThonBhgkTiKfhr57biO/NLLZOXf7HEXe/PA322jEMMYbohgWfcaFspUDQcVpfNA==", - "dev": true, "dependencies": { "@gnosis.pm/mock-contract": "^4.0.0", "@gnosis.pm/safe-contracts": "1.3.0", @@ -881,7 +919,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, "engines": { "node": ">= 12" } @@ -890,7 +927,6 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true, "engines": { "node": ">=10" } @@ -899,7 +935,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, "funding": [ { "type": "individual", @@ -947,7 +982,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -956,7 +990,6 @@ "version": "0.8.25", "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.25.tgz", "integrity": "sha512-7P0TF8gPeudl1Ko3RGkyY6XVCxe2SdD/qQhtns1vl3yAbK/PDifKDLHGtx1t7mX3LgR7ojV7Fg/Kc6Q9D2T8UQ==", - "dev": true, "dependencies": { "command-exists": "^1.2.8", "commander": "^8.1.0", @@ -973,11 +1006,42 @@ "node": ">=10.0.0" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "peer": true, "engines": { "node": ">=6.0.0" @@ -987,14 +1051,12 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true, "peer": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1005,7 +1067,6 @@ "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, "dependencies": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^6.2.1", @@ -1021,7 +1082,6 @@ "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, "dependencies": { "@types/node": "*" } @@ -1029,14 +1089,12 @@ "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/@metamask/eth-sig-util/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, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -1051,7 +1109,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "1.3.2" @@ -1064,7 +1121,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "dev": true, "peer": true, "engines": { "node": ">= 16" @@ -1077,7 +1133,6 @@ "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", @@ -1089,8 +1144,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1103,8 +1156,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "peer": true, "engines": { "node": ">= 8" } @@ -1113,8 +1164,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1127,7 +1176,6 @@ "version": "0.3.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.4.tgz", "integrity": "sha512-e4jzVeJ+VTKBFzNgKDbSVnGVbHYNZHIfMdgifQBugXPiIa6QEUzZqleh2+y4lhkXcCthnFyrTYe3jiEpUzr3cA==", - "dev": true, "engines": { "node": ">= 18" }, @@ -1150,7 +1198,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1166,7 +1213,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1182,7 +1228,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1198,7 +1243,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1214,7 +1258,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1230,7 +1273,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1246,7 +1288,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1262,7 +1303,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1278,7 +1318,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1291,7 +1330,6 @@ "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, "dependencies": { "@nomicfoundation/ethereumjs-util": "9.0.4" } @@ -1300,7 +1338,6 @@ "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, "bin": { "rlp": "bin/rlp.cjs" }, @@ -1312,7 +1349,6 @@ "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, "dependencies": { "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-rlp": "5.0.4", @@ -1335,7 +1371,6 @@ "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, "dependencies": { "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" @@ -1356,7 +1391,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.6.tgz", "integrity": "sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==", - "dev": true, "peer": true, "dependencies": { "@types/chai-as-promised": "^7.1.3", @@ -1375,8 +1409,6 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz", "integrity": "sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw==", - "dev": true, - "peer": true, "dependencies": { "debug": "^4.1.1", "lodash.isequal": "^4.5.0" @@ -1390,7 +1422,6 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.1.tgz", "integrity": "sha512-hWV/W9ZdG9HIqUiQXexrwoBBGP4IrDLghlZPAXXEXETmJ2AVPnBKQG626YmAYgEk2G3vX9ojn16daT+H2i/mFA==", - "dev": true, "peer": true, "dependencies": { "@nomicfoundation/ignition-core": "^0.15.1", @@ -1409,7 +1440,6 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.1.tgz", "integrity": "sha512-FPeE0EbJ+RcBGro9TxODyDffpSPhnG8ra43nJp7/1H2M0S+UkmJUeZlSjAIVfUut1zMwy+57j+PNn07dOr/YmQ==", - "dev": true, "peer": true, "peerDependencies": { "@nomicfoundation/hardhat-ethers": "^3.0.4", @@ -1423,7 +1453,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.10.tgz", "integrity": "sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==", - "dev": true, "peer": true, "dependencies": { "ethereumjs-util": "^7.1.4" @@ -1436,7 +1465,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", - "dev": true, "peerDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", @@ -1462,7 +1490,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.5.tgz", "integrity": "sha512-Tg4zu8RkWpyADSFIgF4FlJIUEI4VkxcvELsmbJn2OokbvH2SnUrqKmw0BBfDrtvP0hhmx8wsnrRKP5DV/oTyTA==", - "dev": true, "peer": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -1483,7 +1510,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "peer": true, "dependencies": { "color-convert": "^1.9.0" @@ -1496,7 +1522,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "peer": true, "dependencies": { "ansi-styles": "^3.2.1", @@ -1511,7 +1536,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "peer": true, "dependencies": { "color-name": "1.1.3" @@ -1521,14 +1545,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "peer": true }, "node_modules/@nomicfoundation/hardhat-verify/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "peer": true, "engines": { "node": ">=0.8.0" @@ -1538,7 +1560,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -1548,7 +1569,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -1561,7 +1581,6 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.1.tgz", "integrity": "sha512-/AZO0YHRv1+yQSOtSSbg4GEH9YhU8EVePSfByU2PZW2bsAK0SA8GdoLYFbVNl140dogem5lrE+bCKtX0eN/n+A==", - "dev": true, "peer": true, "dependencies": { "@ethersproject/address": "5.6.1", @@ -1579,7 +1598,6 @@ "version": "5.6.1", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", - "dev": true, "funding": [ { "type": "individual", @@ -1603,7 +1621,6 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", - "dev": true, "peer": true, "dependencies": { "nofilter": "^3.1.0" @@ -1616,14 +1633,12 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.1.tgz", "integrity": "sha512-ecx6M9K4IeF7L0XCcHg0E72zlVaGSOlkhb/9XuWrA2ltfB/e4ZsOhVxXtwDf9xIcaq7tUdMSxyj6Ld0bPAhxAw==", - "dev": true, "peer": true }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", - "dev": true, "engines": { "node": ">= 12" }, @@ -1647,7 +1662,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1663,7 +1677,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1679,7 +1692,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -1695,7 +1707,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1711,7 +1722,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1727,7 +1737,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1743,7 +1752,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1759,7 +1767,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1775,7 +1782,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1791,7 +1797,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1803,26 +1808,27 @@ "node_modules/@openzeppelin/contracts": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", - "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==", - "dev": true + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==" }, "node_modules/@openzeppelin/contracts-upgradeable": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz", - "integrity": "sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==", - "dev": true + "integrity": "sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==" }, "node_modules/@prb/math": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@prb/math/-/math-4.0.3.tgz", - "integrity": "sha512-/RSt3VU1k2m3ox6U6kUL1MrktnAHr8vhydXu4eDtqFAms1gm3XnGpoZIPaK1lm2zdJQmKBwJ4EXALPARsuOlaA==", - "dev": true + "integrity": "sha512-/RSt3VU1k2m3ox6U6kUL1MrktnAHr8vhydXu4eDtqFAms1gm3XnGpoZIPaK1lm2zdJQmKBwJ4EXALPARsuOlaA==" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" }, "node_modules/@scure/base": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", - "dev": true, "funding": { "url": "https://paulmillr.com/funding/" } @@ -1831,7 +1837,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", - "dev": true, "peer": true, "dependencies": { "@noble/curves": "~1.3.0", @@ -1846,7 +1851,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "1.3.3" @@ -1859,7 +1863,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, "peer": true, "engines": { "node": ">= 16" @@ -1872,7 +1875,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "~1.3.2", @@ -1886,7 +1888,6 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -1901,14 +1902,12 @@ "node_modules/@sentry/core/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "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, "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -1921,14 +1920,12 @@ "node_modules/@sentry/hub/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "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, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -1941,14 +1938,12 @@ "node_modules/@sentry/minimal/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "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, "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -1967,14 +1962,12 @@ "node_modules/@sentry/node/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "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, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -1989,14 +1982,12 @@ "node_modules/@sentry/tracing/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "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, "engines": { "node": ">=6" } @@ -2005,7 +1996,6 @@ "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, "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -2017,14 +2007,12 @@ "node_modules/@sentry/utils/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 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@solidity-parser/parser": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", - "dev": true, "peer": true, "dependencies": { "antlr4ts": "^0.5.0-alpha.4" @@ -2034,35 +2022,30 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, "peer": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, "peer": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, "peer": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, "peer": true }, "node_modules/@typechain/ethers-v6": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", - "dev": true, "peer": true, "dependencies": { "lodash": "^4.17.15", @@ -2078,7 +2061,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", - "dev": true, "peer": true, "dependencies": { "fs-extra": "^9.1.0" @@ -2094,7 +2076,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, "peer": true, "dependencies": { "at-least-node": "^1.0.0", @@ -2110,7 +2091,6 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -2119,14 +2099,12 @@ "version": "4.3.14", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", - "dev": true, "peer": true }, "node_modules/@types/chai-as-promised": { "version": "7.1.8", "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", - "dev": true, "peer": true, "dependencies": { "@types/chai": "*" @@ -2136,7 +2114,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", - "dev": true, "peer": true, "dependencies": { "@types/node": "*" @@ -2146,7 +2123,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", - "dev": true, "peer": true, "dependencies": { "@types/node": "*" @@ -2156,38 +2132,38 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, "peer": true, "dependencies": { "@types/minimatch": "*", "@types/node": "*" } }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, "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 + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, "peer": true }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", - "dev": true, "peer": true }, "node_modules/@types/node": { "version": "20.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2196,7 +2172,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -2205,37 +2180,265 @@ "version": "2.7.3", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, "peer": true }, "node_modules/@types/qs": { "version": "6.9.14", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", - "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", - "dev": true + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==" }, "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, "dependencies": { "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, "node_modules/abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", - "dev": true, "peer": true }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2243,11 +2446,18 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, "peer": true, "engines": { "node": ">=0.4.0" @@ -2257,7 +2467,6 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, "engines": { "node": ">=0.3.0" } @@ -2266,14 +2475,12 @@ "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "dev": true, "peer": true }, "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, "dependencies": { "debug": "4" }, @@ -2285,7 +2492,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -2298,7 +2504,6 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -2315,7 +2520,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", - "dev": true, "optional": true, "peer": true, "engines": { @@ -2326,7 +2530,6 @@ "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, "dependencies": { "string-width": "^4.1.0" } @@ -2335,7 +2538,6 @@ "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, "engines": { "node": ">=6" } @@ -2344,7 +2546,6 @@ "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, "dependencies": { "type-fest": "^0.21.3" }, @@ -2359,7 +2560,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2368,7 +2568,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -2383,14 +2582,12 @@ "version": "0.5.0-alpha.4", "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "dev": true, "peer": true }, "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, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2403,21 +2600,18 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, "peer": true }, "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 + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/argv": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", "integrity": "sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, "engines": { "node": ">=0.6.10" } @@ -2426,7 +2620,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, "peer": true, "engines": { "node": ">=6" @@ -2436,7 +2629,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -2448,12 +2640,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -2462,7 +2671,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, "peer": true, "engines": { "node": ">=0.10.0" @@ -2472,7 +2680,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2488,11 +2695,63 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -2514,15 +2773,12 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, "peer": true }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "peer": true, "engines": { "node": "*" } @@ -2531,7 +2787,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -2541,20 +2796,17 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true, "peer": true }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, "peer": true, "engines": { "node": ">= 4.0.0" @@ -2564,7 +2816,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -2579,7 +2830,6 @@ "version": "1.6.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dev": true, "peer": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -2590,14 +2840,12 @@ "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 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -2605,14 +2853,12 @@ "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, "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, "engines": { "node": ">=8" }, @@ -2623,20 +2869,17 @@ "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 + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" }, "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 + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, "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, "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -2658,7 +2901,6 @@ "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, "engines": { "node": ">=10" }, @@ -2670,7 +2912,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2680,7 +2921,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2691,20 +2931,17 @@ "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 + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, "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 + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "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, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -2718,7 +2955,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, "dependencies": { "base-x": "^3.0.2" } @@ -2727,7 +2963,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -2737,20 +2972,17 @@ "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 + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "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 + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -2759,7 +2991,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2774,11 +3005,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "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, "engines": { "node": ">=10" }, @@ -2790,14 +3028,12 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true, "peer": true }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", - "dev": true, "peer": true, "dependencies": { "nofilter": "^3.1.0" @@ -2810,8 +3046,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "peer": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", @@ -2829,7 +3063,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, "peer": true, "dependencies": { "check-error": "^1.0.2" @@ -2842,7 +3075,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2858,7 +3090,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -2868,8 +3099,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "peer": true, "dependencies": { "get-func-name": "^2.0.2" }, @@ -2881,7 +3110,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2904,14 +3132,12 @@ "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 + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -2921,7 +3147,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "engines": { "node": ">=6" } @@ -2930,7 +3155,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, "engines": { "node": ">=6" }, @@ -2942,7 +3166,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "dev": true, "peer": true, "dependencies": { "object-assign": "^4.1.0", @@ -2959,7 +3182,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -2969,7 +3191,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -2979,7 +3200,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "peer": true, "dependencies": { "is-fullwidth-code-point": "^2.0.0", @@ -2993,7 +3213,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, "peer": true, "dependencies": { "ansi-regex": "^3.0.0" @@ -3006,7 +3225,6 @@ "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, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -3017,7 +3235,6 @@ "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, "dependencies": { "color-name": "~1.1.4" }, @@ -3028,14 +3245,12 @@ "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 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, "peer": true, "engines": { "node": ">=0.1.90" @@ -3045,7 +3260,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -3056,14 +3270,12 @@ "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 + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, "peer": true, "dependencies": { "array-back": "^3.1.0", @@ -3079,7 +3291,6 @@ "version": "6.1.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", - "dev": true, "peer": true, "dependencies": { "array-back": "^4.0.2", @@ -3095,7 +3306,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "peer": true, "dependencies": { "color-convert": "^1.9.0" @@ -3108,7 +3318,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -3118,7 +3327,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "peer": true, "dependencies": { "ansi-styles": "^3.2.1", @@ -3133,7 +3341,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "peer": true, "dependencies": { "color-name": "1.1.3" @@ -3143,14 +3350,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "peer": true }, "node_modules/command-line-usage/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "peer": true, "engines": { "node": ">=0.8.0" @@ -3160,7 +3365,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -3170,7 +3374,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -3183,7 +3386,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -3192,20 +3394,17 @@ "node_modules/commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, "engines": [ "node >= 0.8" ], @@ -3221,7 +3420,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -3237,24 +3435,26 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, "peer": true }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, "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, "engines": { "node": ">= 0.6" } @@ -3263,14 +3463,12 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, "peer": 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, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -3283,7 +3481,6 @@ "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, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -3297,14 +3494,39 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, "peer": true }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -3314,7 +3536,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3331,7 +3552,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -3348,7 +3568,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3365,14 +3584,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", - "dev": true, "peer": true }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -3389,7 +3606,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -3401,8 +3617,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "peer": true, "dependencies": { "type-detect": "^4.0.0" }, @@ -3414,7 +3628,6 @@ "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, "peer": true, "engines": { "node": ">=4.0.0" @@ -3423,15 +3636,12 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -3448,7 +3658,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -3465,7 +3674,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -3474,7 +3682,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -3483,7 +3690,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -3492,7 +3698,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", - "dev": true, "peer": true, "dependencies": { "heap": ">= 0.2.0" @@ -3505,8 +3710,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "peer": true, "dependencies": { "path-type": "^4.0.0" }, @@ -3514,11 +3717,21 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true, "engines": { "node": ">=12" }, @@ -3530,7 +3743,6 @@ "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -3544,26 +3756,22 @@ "node_modules/elliptic/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "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 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encode-utf8": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", - "dev": true + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" }, "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, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -3576,7 +3784,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "engines": { "node": ">=6" } @@ -3585,7 +3792,6 @@ "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -3645,7 +3851,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -3657,7 +3862,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -3666,7 +3870,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -3678,7 +3881,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -3692,7 +3894,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, "dependencies": { "hasown": "^2.0.0" } @@ -3701,7 +3902,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -3718,7 +3918,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "engines": { "node": ">=6" } @@ -3727,7 +3926,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -3739,7 +3937,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", - "dev": true, "peer": true, "dependencies": { "esprima": "^2.7.1", @@ -3758,11 +3955,409 @@ "source-map": "~0.2.0" } }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-typescript": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-18.0.0.tgz", + "integrity": "sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==", + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/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==" + }, + "node_modules/eslint/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true, "peer": true, "bin": { "esparse": "bin/esparse.js", @@ -3772,11 +4367,48 @@ "node": ">=0.10.0" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", - "dev": true, "peer": true, "engines": { "node": ">=0.10.0" @@ -3786,8 +4418,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3796,7 +4426,6 @@ "version": "0.2.27", "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", - "dev": true, "peer": true, "dependencies": { "@solidity-parser/parser": "^0.14.0", @@ -3826,7 +4455,6 @@ "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", @@ -3839,7 +4467,6 @@ "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", @@ -3857,7 +4484,6 @@ "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", @@ -3874,7 +4500,6 @@ "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, "peer": true, "dependencies": { "@noble/hashes": "1.2.0", @@ -3887,7 +4512,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, "funding": [ { "type": "individual", @@ -3936,7 +4560,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz", "integrity": "sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "^1.4.0" @@ -3946,7 +4569,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dev": true, "peer": true, "engines": { "node": ">= 16" @@ -3959,7 +4581,6 @@ "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, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -3982,7 +4603,6 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, "dependencies": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -3992,7 +4612,6 @@ "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, "dependencies": { "@types/node": "*" } @@ -4000,14 +4619,12 @@ "node_modules/ethereumjs-abi/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/ethereumjs-abi/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, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -4022,7 +4639,6 @@ "version": "7.1.5", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, "peer": true, "dependencies": { "@types/bn.js": "^5.1.0", @@ -4039,7 +4655,6 @@ "version": "6.11.1", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", - "dev": true, "funding": [ { "type": "individual", @@ -4068,14 +4683,12 @@ "version": "18.15.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true, "peer": true }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", - "dev": true, "peer": true, "dependencies": { "bn.js": "4.11.6", @@ -4090,14 +4703,12 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true, "peer": true }, "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, "dependencies": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -4111,7 +4722,6 @@ "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, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -4120,16 +4730,12 @@ "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, - "peer": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -4141,28 +4747,39 @@ "node": ">=8.6.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==" + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "peer": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "peer": true, "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4174,7 +4791,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, "peer": true, "dependencies": { "array-back": "^3.0.1" @@ -4187,7 +4803,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -4199,16 +4814,47 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, "bin": { "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, "node_modules/fmix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", - "dev": true, "dependencies": { "imul": "^1.0.0" } @@ -4217,7 +4863,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -4237,7 +4882,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, "dependencies": { "is-callable": "^1.1.3" } @@ -4246,7 +4890,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -4259,14 +4902,12 @@ "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 + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4280,20 +4921,17 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true, "peer": true }, "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 + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "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, "optional": true, "os": [ @@ -4307,7 +4945,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4316,7 +4953,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -4334,7 +4970,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4343,7 +4978,6 @@ "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, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4352,8 +4986,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "peer": true, "engines": { "node": "*" } @@ -4362,7 +4994,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -4381,7 +5012,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -4391,7 +5021,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -4408,7 +5037,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, "peer": true, "dependencies": { "chalk": "^2.4.2", @@ -4422,7 +5050,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "peer": true, "dependencies": { "color-convert": "^1.9.0" @@ -4435,7 +5062,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "peer": true, "dependencies": { "ansi-styles": "^3.2.1", @@ -4450,7 +5076,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "peer": true, "dependencies": { "color-name": "1.1.3" @@ -4460,14 +5085,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "peer": true }, "node_modules/ghost-testrpc/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "peer": true, "engines": { "node": ">=0.8.0" @@ -4477,7 +5100,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -4487,7 +5109,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -4500,7 +5121,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4520,7 +5140,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4532,7 +5151,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, "peer": true, "dependencies": { "global-prefix": "^3.0.0" @@ -4545,7 +5163,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, "peer": true, "dependencies": { "ini": "^1.3.5", @@ -4556,11 +5173,35 @@ "node": ">=6" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -4575,7 +5216,6 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, "peer": true, "dependencies": { "@types/glob": "^7.1.1", @@ -4595,7 +5235,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -4606,14 +5245,17 @@ "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 + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -4634,7 +5276,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4643,7 +5284,6 @@ "version": "2.22.2", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz", "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==", - "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", @@ -4709,7 +5349,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/hardhat-dependency-compiler/-/hardhat-dependency-compiler-1.1.4.tgz", "integrity": "sha512-bEsNwSU2owIcKTRJS1vz/VTI1mILfSYiI/4Zcwee99XC41uQIcDDSvJOdIveeMyO7E50JLg2lZet7oIxTC9Gyg==", - "dev": true, "engines": { "node": ">=14.14.0" }, @@ -4721,7 +5360,6 @@ "version": "0.12.2", "resolved": "https://registry.npmjs.org/hardhat-deploy/-/hardhat-deploy-0.12.2.tgz", "integrity": "sha512-Xp/4Lb5lC/j3kvitaWW5IZN5Meqv5D3kTIifc3ZwBoQtFLN26/fDfRV6MWAAcRO9gH64hZVokvtcDdl/fd7w3A==", - "dev": true, "dependencies": { "@ethersproject/abi": "^5.7.0", "@ethersproject/abstract-signer": "^5.7.0", @@ -4753,7 +5391,6 @@ "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, "dependencies": { "follow-redirects": "^1.14.0" } @@ -4762,7 +5399,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, "funding": [ { "type": "individual", @@ -4810,7 +5446,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", - "dev": true, "peer": true, "dependencies": { "array-uniq": "1.0.3", @@ -4825,7 +5460,6 @@ "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", @@ -4837,7 +5471,6 @@ "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", @@ -4854,7 +5487,6 @@ "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", @@ -4870,7 +5502,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -4882,7 +5513,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4896,7 +5526,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -4904,14 +5533,12 @@ "node_modules/hardhat/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/hardhat/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -4920,7 +5547,6 @@ "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, "dependencies": { "@noble/hashes": "1.2.0", "@noble/secp256k1": "1.7.1", @@ -4932,7 +5558,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -4946,7 +5571,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -4955,7 +5579,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4964,7 +5587,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -4976,7 +5598,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -4985,7 +5606,6 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, "engines": { "node": ">=8.3.0" }, @@ -5006,7 +5626,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5015,7 +5634,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -5024,7 +5642,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -5036,7 +5653,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5048,7 +5664,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5060,7 +5675,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -5075,7 +5689,6 @@ "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, "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -5089,7 +5702,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -5099,7 +5711,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -5111,7 +5722,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "bin": { "he": "bin/he" } @@ -5120,14 +5730,12 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true, "peer": true }, "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, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -5138,7 +5746,6 @@ "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", - "dev": true, "peer": true, "dependencies": { "caseless": "^0.12.0", @@ -5154,7 +5761,6 @@ "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, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -5170,7 +5776,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "dev": true, "peer": true, "dependencies": { "@types/node": "^10.0.3" @@ -5180,14 +5785,12 @@ "version": "10.17.60", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "dev": true, "peer": true }, "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, "dependencies": { "agent-base": "6", "debug": "4" @@ -5200,7 +5803,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -5212,8 +5814,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "peer": true, "engines": { "node": ">= 4" } @@ -5222,7 +5822,6 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", - "dev": true, "peer": true, "funding": { "type": "opencollective", @@ -5232,23 +5831,51 @@ "node_modules/immutable": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "dev": true + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/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==", + "engines": { + "node": ">=4" + } }, "node_modules/imul": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, "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, "engines": { "node": ">=8" } @@ -5257,7 +5884,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5266,21 +5892,18 @@ "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 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "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, "peer": true }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -5294,7 +5917,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, "peer": true, "engines": { "node": ">= 0.10" @@ -5304,7 +5926,6 @@ "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, "dependencies": { "fp-ts": "^1.0.0" } @@ -5313,7 +5934,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -5329,7 +5949,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -5341,7 +5960,6 @@ "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, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5353,7 +5971,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -5369,7 +5986,20 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -5381,7 +6011,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, "dependencies": { "is-typed-array": "^1.1.13" }, @@ -5396,7 +6025,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -5411,7 +6039,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5420,7 +6047,6 @@ "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, "engines": { "node": ">=8" } @@ -5429,7 +6055,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -5441,7 +6066,6 @@ "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, "engines": { "node": ">=6.5.0", "npm": ">=3" @@ -5451,7 +6075,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5463,7 +6086,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -5472,7 +6094,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -5483,11 +6104,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "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, "engines": { "node": ">=8" } @@ -5496,7 +6124,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -5512,7 +6139,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, "dependencies": { "call-bind": "^1.0.7" }, @@ -5527,7 +6153,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -5542,7 +6167,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -5557,7 +6181,6 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, "dependencies": { "which-typed-array": "^1.1.14" }, @@ -5572,7 +6195,6 @@ "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, "engines": { "node": ">=10" }, @@ -5584,7 +6206,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -5596,27 +6217,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, "peer": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "peer": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "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 + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" }, "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, "dependencies": { "argparse": "^2.0.1" }, @@ -5624,25 +6240,43 @@ "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==" + }, "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, "peer": true }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, "peer": true }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -5654,7 +6288,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", - "dev": true, "peer": true, "engines": { "node": "*" @@ -5664,7 +6297,6 @@ "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, "dependencies": { "node-addon-api": "^2.0.0", @@ -5675,11 +6307,18 @@ "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==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "peer": true, "engines": { "node": ">=0.10.0" @@ -5689,7 +6328,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.9" } @@ -5698,7 +6336,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, "peer": true, "engines": { "node": ">=6" @@ -5708,7 +6345,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, "peer": true, "dependencies": { "prelude-ls": "~1.1.2", @@ -5722,7 +6358,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -5734,42 +6369,40 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "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, "peer": true }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, "peer": true }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true, - "peer": true + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "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==" }, "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, "peer": true }, "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, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -5785,8 +6418,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "peer": true, "dependencies": { "get-func-name": "^2.0.1" } @@ -5794,14 +6425,12 @@ "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 + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "peer": true, "dependencies": { "yallist": "^4.0.0" @@ -5814,27 +6443,23 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, "peer": true }, "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true, "peer": true }, "node_modules/match-all": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz", - "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==", - "dev": true + "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==" }, "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, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -5845,7 +6470,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, "engines": { "node": ">= 0.10.0" } @@ -5854,8 +6478,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "peer": true, "engines": { "node": ">= 8" } @@ -5864,15 +6486,12 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", - "dev": true, "peer": true }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "peer": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -5885,7 +6504,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5894,7 +6512,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -5905,20 +6522,17 @@ "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 + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "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 + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5930,7 +6544,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5939,7 +6552,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "peer": true, "dependencies": { "minimist": "^1.2.6" @@ -5952,7 +6564,6 @@ "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, "dependencies": { "obliterator": "^2.0.0" } @@ -5961,7 +6572,6 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -5996,7 +6606,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, "engines": { "node": ">=6" } @@ -6005,7 +6614,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -6014,7 +6622,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -6041,7 +6648,6 @@ "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, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -6057,7 +6663,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6076,7 +6681,6 @@ "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, "dependencies": { "p-locate": "^5.0.0" }, @@ -6091,7 +6695,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6102,14 +6705,12 @@ "node_modules/mocha/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 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mocha/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, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -6124,7 +6725,6 @@ "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, "dependencies": { "p-limit": "^3.0.2" }, @@ -6139,7 +6739,6 @@ "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, "engines": { "node": ">=8" } @@ -6148,7 +6747,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6162,25 +6760,27 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/murmur-128": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/murmur-128/-/murmur-128-0.2.1.tgz", "integrity": "sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==", - "dev": true, "dependencies": { "encode-utf8": "^1.0.2", "fmix": "^0.1.0", "imul": "^1.0.0" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, "node_modules/ndjson": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", - "dev": true, "peer": true, "dependencies": { "json-stringify-safe": "^5.0.1", @@ -6199,20 +6799,17 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "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 + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, "peer": true, "dependencies": { "lodash": "^4.17.21" @@ -6222,7 +6819,6 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -6233,7 +6829,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", - "dev": true, "peer": true, "engines": { "node": ">=12.19" @@ -6243,7 +6838,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, "peer": true, "dependencies": { "abbrev": "1" @@ -6256,7 +6850,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6265,7 +6858,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", - "dev": true, "peer": true, "dependencies": { "bn.js": "4.11.6", @@ -6280,14 +6872,12 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true, "peer": true }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "peer": true, "engines": { "node": ">=0.10.0" @@ -6297,7 +6887,6 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6306,7 +6895,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -6315,7 +6903,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -6329,17 +6916,74 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", - "dev": true + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" }, "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, "dependencies": { "wrappy": "1" } @@ -6348,7 +6992,6 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, "peer": true, "dependencies": { "deep-is": "~0.1.3", @@ -6366,14 +7009,12 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", - "dev": true, "peer": true }, "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, "engines": { "node": ">=0.10.0" } @@ -6382,7 +7023,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -6394,7 +7034,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -6406,7 +7045,6 @@ "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, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -6421,23 +7059,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, "engines": { "node": ">=4" } }, + "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==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true, "peer": true }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, "engines": { "node": ">=4" } @@ -6446,23 +7092,27 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "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==", + "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 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "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, - "peer": true, "engines": { "node": ">=8" } @@ -6471,8 +7121,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "peer": true, "engines": { "node": "*" } @@ -6481,7 +7129,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -6497,7 +7144,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -6509,7 +7155,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "peer": true, "engines": { "node": ">=6" @@ -6519,7 +7164,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -6528,23 +7172,20 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, "peer": true, "engines": { "node": ">= 0.8.0" } }, "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, - "peer": true, + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -6554,14 +7195,12 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, "peer": true }, "node_modules/promise": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "dev": true, "peer": true, "dependencies": { "asap": "~2.0.6" @@ -6571,7 +7210,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "peer": true, "dependencies": { "kleur": "^3.0.3", @@ -6585,15 +7223,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, "peer": true }, "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, - "peer": true, "engines": { "node": ">=6" } @@ -6602,7 +7237,6 @@ "version": "6.12.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", - "dev": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -6617,7 +7251,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -6631,14 +7264,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "peer": true + ] }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -6647,7 +7278,6 @@ "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, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6662,7 +7292,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6676,7 +7305,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -6688,7 +7316,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, "peer": true, "dependencies": { "resolve": "^1.1.6" @@ -6701,7 +7328,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dev": true, "peer": true, "dependencies": { "minimatch": "^3.0.5" @@ -6714,7 +7340,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, "peer": true, "engines": { "node": ">=6" @@ -6724,7 +7349,6 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -6742,7 +7366,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", - "dev": true, "peer": true, "dependencies": { "req-from": "^2.0.0" @@ -6755,7 +7378,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", - "dev": true, "peer": true, "dependencies": { "resolve-from": "^3.0.0" @@ -6768,7 +7390,6 @@ "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, "engines": { "node": ">=0.10.0" } @@ -6777,7 +7398,6 @@ "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, "engines": { "node": ">=0.10.0" } @@ -6786,7 +7406,6 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, "dependencies": { "path-parse": "^1.0.6" }, @@ -6798,7 +7417,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -6808,8 +7426,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "peer": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -6819,7 +7435,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -6831,7 +7446,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -6841,7 +7455,6 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "dev": true, "dependencies": { "bn.js": "^5.2.0" }, @@ -6853,7 +7466,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -6868,7 +7480,6 @@ "url": "https://feross.org/support" } ], - "peer": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -6877,7 +7488,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -6894,14 +7504,12 @@ "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "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", @@ -6921,7 +7529,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -6937,14 +7544,12 @@ "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 + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sc-istanbul": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", - "dev": true, "peer": true, "dependencies": { "abbrev": "1.0.x", @@ -6970,7 +7575,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -6980,7 +7584,6 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "dev": true, "peer": true, "dependencies": { "inflight": "^1.0.4", @@ -6997,7 +7600,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true, "peer": true, "engines": { "node": ">=0.10.0" @@ -7007,7 +7609,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -7021,7 +7622,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "peer": true, "bin": { "esparse": "bin/esparse.js", @@ -7035,14 +7635,12 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true, "peer": true }, "node_modules/sc-istanbul/node_modules/supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, "peer": true, "dependencies": { "has-flag": "^1.0.0" @@ -7054,14 +7652,12 @@ "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 + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "node_modules/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "dev": true, "hasInstallScript": true, "dependencies": { "elliptic": "^6.5.4", @@ -7076,7 +7672,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -7085,7 +7680,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -7094,7 +7688,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7111,7 +7704,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7125,20 +7717,17 @@ "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 + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "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, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -7151,7 +7740,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", - "dev": true, "peer": true, "dependencies": { "charenc": ">= 0.0.1", @@ -7161,11 +7749,29 @@ "node": "*" } }, + "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==", + "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==", + "engines": { + "node": ">=8" + } + }, "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, "peer": true, "dependencies": { "glob": "^7.0.0", @@ -7183,7 +7789,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -7201,15 +7806,12 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, "peer": true }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -7218,7 +7820,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "peer": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -7236,7 +7837,6 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, "dependencies": { "command-exists": "^1.2.8", "commander": "3.0.2", @@ -7259,7 +7859,6 @@ "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^2.1.0", @@ -7272,7 +7871,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7281,7 +7879,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -7290,7 +7887,6 @@ "version": "0.4.56", "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.56.tgz", "integrity": "sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==", - "dev": true, "dependencies": { "array.prototype.findlast": "^1.2.2" } @@ -7299,7 +7895,6 @@ "version": "0.8.12", "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.12.tgz", "integrity": "sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==", - "dev": true, "peer": true, "dependencies": { "@ethersproject/abi": "^5.0.9", @@ -7333,14 +7928,12 @@ "version": "0.18.0", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", - "dev": true, "peer": true }, "node_modules/solidity-coverage/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "peer": true, "dependencies": { "color-convert": "^1.9.0" @@ -7353,7 +7946,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "peer": true, "dependencies": { "ansi-styles": "^3.2.1", @@ -7368,7 +7960,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "peer": true, "dependencies": { "color-name": "1.1.3" @@ -7378,14 +7969,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "peer": true }, "node_modules/solidity-coverage/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "peer": true, "engines": { "node": ">=0.8.0" @@ -7395,7 +7984,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -7410,7 +7998,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "peer": true, "engines": { "node": ">=4" @@ -7420,7 +8007,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -7430,7 +8016,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "peer": true, "dependencies": { "lru-cache": "^6.0.0" @@ -7446,7 +8031,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -7459,7 +8043,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "peer": true, "engines": { "node": ">= 4.0.0" @@ -7469,7 +8052,6 @@ "version": "0.6.0-beta.36", "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.36.tgz", "integrity": "sha512-f/I5G2iJgU1h0XrrjRD0hHMr7C10u276vYvm//rw1TzFcYQ4xTOyAoi9oNAHRU0JU4mY9eTuxdVc2zahdMuhaQ==", - "dev": true, "dependencies": { "handlebars": "^4.7.7", "solidity-ast": "^0.4.38" @@ -7482,7 +8064,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", - "dev": true, "optional": true, "peer": true, "dependencies": { @@ -7496,7 +8077,6 @@ "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, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7506,7 +8086,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7515,7 +8094,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, "peer": true, "dependencies": { "readable-stream": "^3.0.0" @@ -7525,14 +8103,12 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, "peer": true }, "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, "dependencies": { "type-fest": "^0.7.1" }, @@ -7544,7 +8120,6 @@ "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, "engines": { "node": ">=8" } @@ -7553,7 +8128,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -7562,7 +8136,6 @@ "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, "dependencies": { "safe-buffer": "~5.2.0" } @@ -7571,14 +8144,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true, "peer": true }, "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, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7592,7 +8163,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7610,7 +8180,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7624,7 +8193,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7641,7 +8209,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -7649,11 +8216,18 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, "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, "dependencies": { "is-hex-prefixed": "1.0.0" }, @@ -7666,7 +8240,6 @@ "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, "engines": { "node": ">=8" }, @@ -7678,7 +8251,6 @@ "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, "dependencies": { "has-flag": "^4.0.0" }, @@ -7686,11 +8258,21 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sync-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", - "dev": true, "peer": true, "dependencies": { "http-response-object": "^3.0.1", @@ -7705,7 +8287,6 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", - "dev": true, "peer": true, "dependencies": { "get-port": "^3.1.0" @@ -7715,7 +8296,6 @@ "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", - "dev": true, "peer": true, "dependencies": { "ajv": "^8.0.1", @@ -7732,7 +8312,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", - "dev": true, "peer": true, "dependencies": { "array-back": "^4.0.1", @@ -7748,7 +8327,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -7758,17 +8336,20 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, "peer": true, "engines": { "node": ">=8" } }, + "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==" + }, "node_modules/then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", - "dev": true, "peer": true, "dependencies": { "@types/concat-stream": "^1.6.0", @@ -7791,14 +8372,12 @@ "version": "8.10.66", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "dev": true, "peer": true }, "node_modules/then-request/node_modules/form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, "peer": true, "dependencies": { "asynckit": "^0.4.0", @@ -7813,7 +8392,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, "peer": true, "dependencies": { "readable-stream": "3" @@ -7823,7 +8401,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -7835,7 +8412,6 @@ "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, "dependencies": { "is-number": "^7.0.0" }, @@ -7847,16 +8423,25 @@ "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, "engines": { "node": ">=0.6" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-command-line-args": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", - "dev": true, "peer": true, "dependencies": { "chalk": "^4.1.0", @@ -7872,7 +8457,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, "peer": true, "peerDependencies": { "typescript": ">=3.7.0" @@ -7882,7 +8466,6 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -7926,42 +8509,47 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "peer": true, "engines": { "node": ">=0.3.1" } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true, "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 + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" }, "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 + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, "peer": true, "dependencies": { "prelude-ls": "~1.1.2" @@ -7974,8 +8562,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "peer": true, "engines": { "node": ">=4" } @@ -7984,7 +8570,6 @@ "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, "engines": { "node": ">=10" }, @@ -7996,7 +8581,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", - "dev": true, "peer": true, "dependencies": { "@types/prettier": "^2.1.1", @@ -8021,7 +8605,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, "peer": true, "dependencies": { "graceful-fs": "^4.1.2", @@ -8036,7 +8619,6 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -8057,7 +8639,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -8067,7 +8648,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "peer": true, "bin": { "mkdirp": "bin/cmd.js" @@ -8076,11 +8656,25 @@ "node": ">=10" } }, + "node_modules/typechain/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/typechain/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, "peer": true, "engines": { "node": ">= 4.0.0" @@ -8090,7 +8684,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -8104,7 +8697,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -8123,7 +8715,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -8143,7 +8734,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -8163,14 +8753,12 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, "peer": true }, "node_modules/typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -8184,7 +8772,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -8194,7 +8781,6 @@ "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -8207,7 +8793,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -8222,7 +8807,6 @@ "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -8233,14 +8817,12 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "engines": { "node": ">= 10.0.0" } @@ -8249,7 +8831,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -8258,8 +8839,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "peer": true, "dependencies": { "punycode": "^2.1.0" } @@ -8268,20 +8847,17 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true, "peer": true }, "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 + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "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, "bin": { "uuid": "dist/bin/uuid" } @@ -8290,14 +8866,12 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, "peer": true }, "node_modules/web3-utils": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", - "dev": true, "peer": true, "dependencies": { "@ethereumjs/util": "^8.1.0", @@ -8317,7 +8891,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "dev": true, "peer": true, "dependencies": { "@noble/hashes": "1.3.3" @@ -8330,7 +8903,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, "peer": true, "engines": { "node": ">= 16" @@ -8343,7 +8915,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", - "dev": true, "peer": true, "dependencies": { "@noble/curves": "1.3.0", @@ -8356,7 +8927,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "peer": true, "dependencies": { "isexe": "^2.0.0" @@ -8369,7 +8939,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -8385,7 +8954,6 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -8404,7 +8972,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, "dependencies": { "string-width": "^4.0.0" }, @@ -8416,8 +8983,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -8425,14 +8990,12 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", - "dev": true, "peer": true, "dependencies": { "reduce-flatten": "^2.0.0", @@ -8446,7 +9009,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, "peer": true, "engines": { "node": ">=8" @@ -8455,14 +9017,12 @@ "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" }, "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, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8478,14 +9038,12 @@ "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 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, "peer": true, "engines": { "node": ">=10.0.0" @@ -8507,7 +9065,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -8516,14 +9073,12 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, "peer": true }, "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, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -8541,7 +9096,6 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, "engines": { "node": ">=10" } @@ -8550,7 +9104,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -8565,7 +9118,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, "peer": true, "engines": { "node": ">=6" @@ -8575,7 +9127,6 @@ "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, "engines": { "node": ">=10" }, @@ -8587,7 +9138,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/zksync-ethers/-/zksync-ethers-5.7.0.tgz", "integrity": "sha512-X99c5APICTlRzyXXjfwkEjRzOPp3Jwo62+z2DVGaZbe+b9Apbizcd2UGV4NGomoAR2GXPbeiSqi1cf3Hbo3cQw==", - "dev": true, "dependencies": { "ethers": "~5.7.0" }, @@ -8602,7 +9152,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, "funding": [ { "type": "individual", diff --git a/package.json b/package.json index 7a7fce94..55e0d734 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,10 @@ "url": "git+https://github.com/decentdao/fractal-contracts.git" }, "scripts": { + "lint": "eslint . --ext .ts --fix", + "lint:check": "eslint . --ext .ts", + "pretty": "prettier . --write", + "pretty:check": "prettier . --check", "clean": "hardhat clean", "compile": "hardhat compile", "docgen": "hardhat docgen", @@ -25,16 +29,25 @@ "bugs": { "url": "https://github.com/decentdao/fractal-contracts/issues" }, - "devDependencies": { + "dependencies": { "@gnosis.pm/zodiac": "^1.1.4", + "@nomicfoundation/hardhat-ethers": "^3.0.5", "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts-upgradeable": "^4.5.0", "@prb/math": "^4.0.3", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "chai": "^4.2.0", "dotenv": "^16.4.5", + "eslint": "^8.22.0", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", "hardhat": "^2.22.2", "hardhat-dependency-compiler": "^1.1.4", "hardhat-deploy": "^0.12.2", + "prettier": "^3.3.3", "solidity-docgen": "^0.6.0-beta.36" } } From 11c995d4c1e4c2ca2343b1bf0b9305b54f8de574 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Tue, 22 Oct 2024 11:09:59 -0400 Subject: [PATCH 2/3] Lint and Pretty all the things --- .github/SECURITY.md | 2 +- .github/workflows/publish.yml | 4 +- .github/workflows/tests.yml | 2 +- deploy/core/001_deploy_ERC20Claim.ts | 8 +- deploy/core/002_deploy_FractalModule.ts | 8 +- deploy/core/003_deploy_FractalRegistry.ts | 10 +- deploy/core/004_deploy_ERC20FreezeVoting.ts | 8 +- .../core/005_deploy_MultisigFreezeVoting.ts | 8 +- deploy/core/006_deploy_MultisigFreezeGuard.ts | 8 +- deploy/core/007_deploy_AzoriusFreezeGuard.ts | 8 +- deploy/core/008_deploy_Azorius.ts | 10 +- deploy/core/009_deploy_VotesERC20.ts | 8 +- deploy/core/010_deploy_LinearERC20Voting.ts | 10 +- deploy/core/011_deploy_ModuleProxyFactory.ts | 2 +- deploy/core/012_deploy_KeyValuePairs.ts | 8 +- deploy/core/013_deploy_VotesERC20Wrapper.ts | 8 +- .../014_deploy_LinearERC20WrappedVoting.ts | 10 +- deploy/core/015_deploy_LinearERC721Voting.ts | 8 +- deploy/core/016_deploy_ERC721FreezeVoting.ts | 8 +- deploy/core/017_deploy_DecentHats_0_1_0.ts | 8 +- ...18_deploy_DecentSablierStreamManagement.ts | 8 +- deploy/helpers/deployNonUpgradeable.ts | 4 +- hardhat.config.ts | 57 +- test/Atomic-Deployment.test.ts | 493 +++---- test/Azorius-LinearERC20Voting.test.ts | 1170 ++++++----------- test/Azorius-LinearERC721Voting.test.ts | 824 ++++-------- ...oriusFreezeGuard-ERC20FreezeVoting.test.ts | 543 ++++---- ...usFreezeGuard-MultisigFreezeVoting.test.ts | 526 ++++---- test/DecentHats_0_1_0.test.ts | 541 ++++---- test/DecentSablierStreamManagement.test.ts | 361 +++-- test/ERC20-Claim.test.ts | 239 ++-- test/Fractal-Module.test.ts | 255 ++-- test/Fractal-Registry.test.ts | 58 +- test/GlobalSafeDeployments.test.ts | 8 +- ...tisigFreezeGuard-ERC20FreezeVoting.test.ts | 390 +++--- ...isigFreezeGuard-ERC721FreezeVoting.test.ts | 462 +++---- ...igFreezeGuard-MultisigFreezeVoting.test.ts | 489 ++++--- test/helpers.ts | 176 ++- test/time.ts | 10 +- 39 files changed, 2732 insertions(+), 4028 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index bcd55432..d9c81415 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -19,4 +19,4 @@ Please include the following information in your email: If you prefer secure communication, please use the following GPG key: -https://keys.openpgp.org/search?q=security%40decent-dao.org \ No newline at end of file +https://keys.openpgp.org/search?q=security%40decent-dao.org diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7dfec4bd..d02b6fbd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,8 +12,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version-file: ".nvmrc" - registry-url: "https://registry.npmjs.org" + node-version-file: '.nvmrc' + registry-url: 'https://registry.npmjs.org' - run: npm clean-install - run: npm publish env: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8fd3cf7a..d687857c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version-file: ".nvmrc" + node-version-file: '.nvmrc' - run: npm install - run: npm run compile - run: npm run test diff --git a/deploy/core/001_deploy_ERC20Claim.ts b/deploy/core/001_deploy_ERC20Claim.ts index fb32acc0..b3654d3c 100644 --- a/deploy/core/001_deploy_ERC20Claim.ts +++ b/deploy/core/001_deploy_ERC20Claim.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "ERC20Claim", []); + await deployNonUpgradeable(hre, 'ERC20Claim', []); }; export default func; diff --git a/deploy/core/002_deploy_FractalModule.ts b/deploy/core/002_deploy_FractalModule.ts index a14f30ad..de8e0b58 100644 --- a/deploy/core/002_deploy_FractalModule.ts +++ b/deploy/core/002_deploy_FractalModule.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "FractalModule", []); + await deployNonUpgradeable(hre, 'FractalModule', []); }; export default func; diff --git a/deploy/core/003_deploy_FractalRegistry.ts b/deploy/core/003_deploy_FractalRegistry.ts index 64eb718d..2a01c648 100644 --- a/deploy/core/003_deploy_FractalRegistry.ts +++ b/deploy/core/003_deploy_FractalRegistry.ts @@ -1,11 +1,11 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "FractalRegistry", []); + await deployNonUpgradeable(hre, 'FractalRegistry', []); }; -func.tags = ["FractalRegistry"]; +func.tags = ['FractalRegistry']; export default func; diff --git a/deploy/core/004_deploy_ERC20FreezeVoting.ts b/deploy/core/004_deploy_ERC20FreezeVoting.ts index 5b6e2d75..d84e00e7 100644 --- a/deploy/core/004_deploy_ERC20FreezeVoting.ts +++ b/deploy/core/004_deploy_ERC20FreezeVoting.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "ERC20FreezeVoting", []); + await deployNonUpgradeable(hre, 'ERC20FreezeVoting', []); }; export default func; diff --git a/deploy/core/005_deploy_MultisigFreezeVoting.ts b/deploy/core/005_deploy_MultisigFreezeVoting.ts index a1876c4c..de7df8b3 100644 --- a/deploy/core/005_deploy_MultisigFreezeVoting.ts +++ b/deploy/core/005_deploy_MultisigFreezeVoting.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "MultisigFreezeVoting", []); + await deployNonUpgradeable(hre, 'MultisigFreezeVoting', []); }; export default func; diff --git a/deploy/core/006_deploy_MultisigFreezeGuard.ts b/deploy/core/006_deploy_MultisigFreezeGuard.ts index 0ff837db..7b6c4a25 100644 --- a/deploy/core/006_deploy_MultisigFreezeGuard.ts +++ b/deploy/core/006_deploy_MultisigFreezeGuard.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "MultisigFreezeGuard", []); + await deployNonUpgradeable(hre, 'MultisigFreezeGuard', []); }; export default func; diff --git a/deploy/core/007_deploy_AzoriusFreezeGuard.ts b/deploy/core/007_deploy_AzoriusFreezeGuard.ts index 911f520d..89c4f466 100644 --- a/deploy/core/007_deploy_AzoriusFreezeGuard.ts +++ b/deploy/core/007_deploy_AzoriusFreezeGuard.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "AzoriusFreezeGuard", []); + await deployNonUpgradeable(hre, 'AzoriusFreezeGuard', []); }; export default func; diff --git a/deploy/core/008_deploy_Azorius.ts b/deploy/core/008_deploy_Azorius.ts index ac92807b..2b929dfc 100644 --- a/deploy/core/008_deploy_Azorius.ts +++ b/deploy/core/008_deploy_Azorius.ts @@ -1,11 +1,11 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "Azorius", []); + await deployNonUpgradeable(hre, 'Azorius', []); }; -func.tags = ["Azorius"]; +func.tags = ['Azorius']; export default func; diff --git a/deploy/core/009_deploy_VotesERC20.ts b/deploy/core/009_deploy_VotesERC20.ts index dfce6a8b..0aa38973 100644 --- a/deploy/core/009_deploy_VotesERC20.ts +++ b/deploy/core/009_deploy_VotesERC20.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "VotesERC20", []); + await deployNonUpgradeable(hre, 'VotesERC20', []); }; export default func; diff --git a/deploy/core/010_deploy_LinearERC20Voting.ts b/deploy/core/010_deploy_LinearERC20Voting.ts index c746864c..3c511130 100644 --- a/deploy/core/010_deploy_LinearERC20Voting.ts +++ b/deploy/core/010_deploy_LinearERC20Voting.ts @@ -1,16 +1,16 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const chainId = await hre.getChainId(); // See https://github.com/decentdao/decent-contracts/pull/96 - if (chainId === "1" || chainId === "137") { + if (chainId === '1' || chainId === '137') { return; } - await deployNonUpgradeable(hre, "LinearERC20Voting", []); + await deployNonUpgradeable(hre, 'LinearERC20Voting', []); }; export default func; diff --git a/deploy/core/011_deploy_ModuleProxyFactory.ts b/deploy/core/011_deploy_ModuleProxyFactory.ts index 7d2b45e8..52117033 100644 --- a/deploy/core/011_deploy_ModuleProxyFactory.ts +++ b/deploy/core/011_deploy_ModuleProxyFactory.ts @@ -1,5 +1,5 @@ // import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; +import { DeployFunction } from 'hardhat-deploy/types'; // import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; const func: DeployFunction = async (/* hre: HardhatRuntimeEnvironment */) => { diff --git a/deploy/core/012_deploy_KeyValuePairs.ts b/deploy/core/012_deploy_KeyValuePairs.ts index b41565e1..3ba7ada5 100644 --- a/deploy/core/012_deploy_KeyValuePairs.ts +++ b/deploy/core/012_deploy_KeyValuePairs.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "KeyValuePairs", []); + await deployNonUpgradeable(hre, 'KeyValuePairs', []); }; export default func; diff --git a/deploy/core/013_deploy_VotesERC20Wrapper.ts b/deploy/core/013_deploy_VotesERC20Wrapper.ts index cfa4653f..2c412871 100644 --- a/deploy/core/013_deploy_VotesERC20Wrapper.ts +++ b/deploy/core/013_deploy_VotesERC20Wrapper.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "VotesERC20Wrapper", []); + await deployNonUpgradeable(hre, 'VotesERC20Wrapper', []); }; export default func; diff --git a/deploy/core/014_deploy_LinearERC20WrappedVoting.ts b/deploy/core/014_deploy_LinearERC20WrappedVoting.ts index 4609621f..0194982a 100644 --- a/deploy/core/014_deploy_LinearERC20WrappedVoting.ts +++ b/deploy/core/014_deploy_LinearERC20WrappedVoting.ts @@ -1,16 +1,16 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const chainId = await hre.getChainId(); // See https://github.com/decentdao/decent-contracts/pull/96 - if (chainId === "1" || chainId === "137") { + if (chainId === '1' || chainId === '137') { return; } - await deployNonUpgradeable(hre, "LinearERC20WrappedVoting", []); + await deployNonUpgradeable(hre, 'LinearERC20WrappedVoting', []); }; export default func; diff --git a/deploy/core/015_deploy_LinearERC721Voting.ts b/deploy/core/015_deploy_LinearERC721Voting.ts index 1366f7a7..4aa4266c 100644 --- a/deploy/core/015_deploy_LinearERC721Voting.ts +++ b/deploy/core/015_deploy_LinearERC721Voting.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "LinearERC721Voting", []); + await deployNonUpgradeable(hre, 'LinearERC721Voting', []); }; export default func; diff --git a/deploy/core/016_deploy_ERC721FreezeVoting.ts b/deploy/core/016_deploy_ERC721FreezeVoting.ts index 25a3a038..f656d2e0 100644 --- a/deploy/core/016_deploy_ERC721FreezeVoting.ts +++ b/deploy/core/016_deploy_ERC721FreezeVoting.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "ERC721FreezeVoting", []); + await deployNonUpgradeable(hre, 'ERC721FreezeVoting', []); }; export default func; diff --git a/deploy/core/017_deploy_DecentHats_0_1_0.ts b/deploy/core/017_deploy_DecentHats_0_1_0.ts index 6272efd1..89a6ec97 100644 --- a/deploy/core/017_deploy_DecentHats_0_1_0.ts +++ b/deploy/core/017_deploy_DecentHats_0_1_0.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "DecentHats_0_1_0"); + await deployNonUpgradeable(hre, 'DecentHats_0_1_0'); }; export default func; diff --git a/deploy/core/018_deploy_DecentSablierStreamManagement.ts b/deploy/core/018_deploy_DecentSablierStreamManagement.ts index fb33345a..8e406ced 100644 --- a/deploy/core/018_deploy_DecentSablierStreamManagement.ts +++ b/deploy/core/018_deploy_DecentSablierStreamManagement.ts @@ -1,9 +1,9 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { deployNonUpgradeable } from "../helpers/deployNonUpgradeable"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; +import { deployNonUpgradeable } from '../helpers/deployNonUpgradeable'; const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - await deployNonUpgradeable(hre, "DecentSablierStreamManagement"); + await deployNonUpgradeable(hre, 'DecentSablierStreamManagement'); }; export default func; diff --git a/deploy/helpers/deployNonUpgradeable.ts b/deploy/helpers/deployNonUpgradeable.ts index 60122576..df1679a6 100644 --- a/deploy/helpers/deployNonUpgradeable.ts +++ b/deploy/helpers/deployNonUpgradeable.ts @@ -1,10 +1,10 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; const deployNonUpgradeable = async ( hre: HardhatRuntimeEnvironment, contractName: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any - args: any[] = [] + args: any[] = [], ): Promise => { const { deployments: { deploy }, diff --git a/hardhat.config.ts b/hardhat.config.ts index 9f896ddf..cb5b060d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,21 +1,20 @@ -import * as dotenv from "dotenv"; -import { HardhatUserConfig } from "hardhat/config"; -import "@nomicfoundation/hardhat-toolbox"; -import "hardhat-dependency-compiler"; -import "hardhat-deploy"; -import "solidity-docgen"; +import * as dotenv from 'dotenv'; +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; +import 'hardhat-dependency-compiler'; +import 'hardhat-deploy'; +import 'solidity-docgen'; dotenv.config(); // first address from `test test test test test test test test test test test junk` -const dummyPrivateKey = - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; +const dummyPrivateKey = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; const config: HardhatUserConfig = { solidity: { compilers: [ { - version: "0.8.19", + version: '0.8.19', settings: { optimizer: { enabled: true, @@ -24,7 +23,7 @@ const config: HardhatUserConfig = { }, }, { - version: "0.8.28", + version: '0.8.28', settings: { optimizer: { enabled: true, @@ -36,10 +35,10 @@ const config: HardhatUserConfig = { }, dependencyCompiler: { paths: [ - "@gnosis.pm/safe-contracts/contracts/libraries/MultiSendCallOnly.sol", - "@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol", - "@gnosis.pm/safe-contracts/contracts/GnosisSafeL2.sol", - "@gnosis.pm/zodiac/contracts/factory/ModuleProxyFactory.sol", + '@gnosis.pm/safe-contracts/contracts/libraries/MultiSendCallOnly.sol', + '@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol', + '@gnosis.pm/safe-contracts/contracts/GnosisSafeL2.sol', + '@gnosis.pm/zodiac/contracts/factory/ModuleProxyFactory.sol', ], }, namedAccounts: { @@ -55,41 +54,35 @@ const config: HardhatUserConfig = { networks: { mainnet: { chainId: 1, - url: - process.env.MAINNET_PROVIDER || "https://ethereum-rpc.publicnode.com", + url: process.env.MAINNET_PROVIDER || 'https://ethereum-rpc.publicnode.com', accounts: process.env.MAINNET_DEPLOYER_PRIVATE_KEY ? [process.env.MAINNET_DEPLOYER_PRIVATE_KEY] : [dummyPrivateKey], }, sepolia: { chainId: 11155111, - url: - process.env.SEPOLIA_PROVIDER || - "https://ethereum-sepolia-rpc.publicnode.com", + url: process.env.SEPOLIA_PROVIDER || 'https://ethereum-sepolia-rpc.publicnode.com', accounts: process.env.SEPOLIA_DEPLOYER_PRIVATE_KEY ? [process.env.SEPOLIA_DEPLOYER_PRIVATE_KEY] : [dummyPrivateKey], }, polygon: { chainId: 137, - url: - process.env.POLYGON_PROVIDER || - "https://polygon-bor-rpc.publicnode.com", + url: process.env.POLYGON_PROVIDER || 'https://polygon-bor-rpc.publicnode.com', accounts: process.env.POLYGON_DEPLOYER_PRIVATE_KEY ? [process.env.POLYGON_DEPLOYER_PRIVATE_KEY] : [dummyPrivateKey], }, base: { chainId: 8453, - url: process.env.BASE_PROVIDER || "https://base-rpc.publicnode.com", + url: process.env.BASE_PROVIDER || 'https://base-rpc.publicnode.com', accounts: process.env.BASE_DEPLOYER_PRIVATE_KEY ? [process.env.BASE_DEPLOYER_PRIVATE_KEY] : [dummyPrivateKey], }, optimism: { chainId: 10, - url: - process.env.OPTIMISM_PROVIDER || "https://optimism-rpc.publicnode.com", + url: process.env.OPTIMISM_PROVIDER || 'https://optimism-rpc.publicnode.com', accounts: process.env.OPTIMISM_DEPLOYER_PRIVATE_KEY ? [process.env.OPTIMISM_DEPLOYER_PRIVATE_KEY] : [dummyPrivateKey], @@ -97,21 +90,21 @@ const config: HardhatUserConfig = { }, etherscan: { apiKey: { - mainnet: process.env.ETHERSCAN_API_KEY || "", - sepolia: process.env.ETHERSCAN_API_KEY || "", - polygon: process.env.POLYGONSCAN_API_KEY || "", - base: process.env.BASESCAN_API_KEY || "", - optimisticEthereum: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || "", + mainnet: process.env.ETHERSCAN_API_KEY || '', + sepolia: process.env.ETHERSCAN_API_KEY || '', + polygon: process.env.POLYGONSCAN_API_KEY || '', + base: process.env.BASESCAN_API_KEY || '', + optimisticEthereum: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || '', }, }, sourcify: { enabled: true, }, paths: { - deploy: "deploy/core", + deploy: 'deploy/core', }, docgen: { - pages: "files", + pages: 'files', }, }; diff --git a/test/Atomic-Deployment.test.ts b/test/Atomic-Deployment.test.ts index 243aaace..51039dd8 100644 --- a/test/Atomic-Deployment.test.ts +++ b/test/Atomic-Deployment.test.ts @@ -1,7 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { Azorius__factory, FractalModule, @@ -14,23 +13,22 @@ import { MultiSendCallOnly__factory, MultisigFreezeGuard, MultisigFreezeGuard__factory, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, + getMultiSendCallOnly, +} from './GlobalSafeDeployments.test'; import { calculateProxyAddress, predictGnosisSafeAddress, buildContractCall, MetaTransaction, encodeMultiSend, -} from "./helpers"; - -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, - getMultiSendCallOnly, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; -describe("Atomic Gnosis Safe Deployment", () => { +describe('Atomic Gnosis Safe Deployment', () => { // Factories let gnosisSafeProxyFactory: GnosisSafeProxyFactory; @@ -61,9 +59,7 @@ describe("Atomic Gnosis Safe Deployment", () => { const threshold = 2; let predictedFreezeGuard: string; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); @@ -77,13 +73,8 @@ describe("Atomic Gnosis Safe Deployment", () => { // SETUP GnosisSafe createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [ - owner1.address, - owner2.address, - owner3.address, - await multiSendCallOnly.getAddress(), - ], + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ + [owner1.address, owner2.address, owner3.address, await multiSendCallOnly.getAddress()], 1, ethers.ZeroAddress, ethers.ZeroHash, @@ -97,69 +88,50 @@ describe("Atomic Gnosis Safe Deployment", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Get Gnosis Safe contract // eslint-disable-next-line camelcase - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); /// ///////////// GUARD /////////////////// // DEPLOY GUARD - freezeGuardImplementation = await new MultisigFreezeGuard__factory( - deployer - ).deploy(); + freezeGuardImplementation = await new MultisigFreezeGuard__factory(deployer).deploy(); freezeGuardFactoryInit = // eslint-disable-next-line camelcase - MultisigFreezeGuard__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["uint256", "uint256", "address", "address", "address"], - [ - 10, - 20, - owner1.address, - owner1.address, - await gnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeGuard__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['uint256', 'uint256', 'address', 'address', 'address'], + [10, 20, owner1.address, owner1.address, await gnosisSafe.getAddress()], + ), + ]); predictedFreezeGuard = await calculateProxyAddress( moduleProxyFactory, await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, - "10031021" + '10031021', ); - freezeGuard = await hre.ethers.getContractAt( - "MultisigFreezeGuard", - predictedFreezeGuard - ); + freezeGuard = await hre.ethers.getContractAt('MultisigFreezeGuard', predictedFreezeGuard); /// /////////////// MODULE //////////////// // DEPLOY Fractal Module - fractalModuleSingleton = await new FractalModule__factory( - deployer - ).deploy(); + fractalModuleSingleton = await new FractalModule__factory(deployer).deploy(); // SETUP Module setModuleCalldata = // eslint-disable-next-line camelcase - FractalModule__factory.createInterface().encodeFunctionData("setUp", [ + FractalModule__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]"], + ['address', 'address', 'address', 'address[]'], [ owner1.address, await gnosisSafe.getAddress(), await gnosisSafe.getAddress(), [owner2.address], - ] + ], ), ]); @@ -167,106 +139,77 @@ describe("Atomic Gnosis Safe Deployment", () => { moduleProxyFactory, await fractalModuleSingleton.getAddress(), setModuleCalldata, - "10031021" + '10031021', ); - fractalModule = await hre.ethers.getContractAt( - "FractalModule", - predictedFractalModule - ); + fractalModule = await hre.ethers.getContractAt('FractalModule', predictedFractalModule); // TX Array sigs = - "0x000000000000000000000000" + + '0x000000000000000000000000' + (await multiSendCallOnly.getAddress()).slice(2) + - "0000000000000000000000000000000000000000000000000000000000000000" + - "01"; + '0000000000000000000000000000000000000000000000000000000000000000' + + '01'; }); - describe("Atomic Gnosis Safe Deployment", () => { - it("Setup Fractal Module w/ ModuleProxyCreationEvent", async () => { + describe('Atomic Gnosis Safe Deployment', () => { + it('Setup Fractal Module w/ ModuleProxyCreationEvent', async () => { const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await fractalModuleSingleton.getAddress(), - setModuleCalldata, - "10031021", - ], + 'deployModule', + [await fractalModuleSingleton.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(moduleProxyFactory, "ModuleProxyCreation") - .withArgs( - predictedFractalModule, - await fractalModuleSingleton.getAddress() - ); + .to.emit(moduleProxyFactory, 'ModuleProxyCreation') + .withArgs(predictedFractalModule, await fractalModuleSingleton.getAddress()); expect(await fractalModule.avatar()).eq(await gnosisSafe.getAddress()); - expect(await fractalModule.getFunction("target")()).eq( - await gnosisSafe.getAddress() - ); + expect(await fractalModule.getFunction('target')()).eq(await gnosisSafe.getAddress()); expect(await fractalModule.owner()).eq(owner1.address); }); - it("Setup FreezeGuard w/ ModuleProxyCreationEvent", async () => { + it('Setup FreezeGuard w/ ModuleProxyCreationEvent', async () => { const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await freezeGuardImplementation.getAddress(), - freezeGuardFactoryInit, - "10031021", - ], + 'deployModule', + [await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, '10031021'], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(moduleProxyFactory, "ModuleProxyCreation") - .withArgs( - predictedFreezeGuard, - await freezeGuardImplementation.getAddress() - ); + .to.emit(moduleProxyFactory, 'ModuleProxyCreation') + .withArgs(predictedFreezeGuard, await freezeGuardImplementation.getAddress()); expect(await freezeGuard.timelockPeriod()).eq(10); expect(await freezeGuard.freezeVoting()).eq(owner1.address); - expect(await freezeGuard.childGnosisSafe()).eq( - await gnosisSafe.getAddress() - ); + expect(await freezeGuard.childGnosisSafe()).eq(await gnosisSafe.getAddress()); }); - it("Setup Azorius Module w/ ModuleProxyCreationEvent", async () => { + it('Setup Azorius Module w/ ModuleProxyCreationEvent', async () => { const VOTING_STRATEGIES_TO_DEPLOY: string[] = []; const encodedInitAzoriusData = abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ await gnosisSafe.getAddress(), await gnosisSafe.getAddress(), @@ -274,13 +217,11 @@ describe("Atomic Gnosis Safe Deployment", () => { VOTING_STRATEGIES_TO_DEPLOY, 0, 0, - ] + ], ); const encodedSetupAzoriusData = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ - encodedInitAzoriusData, - ]); + Azorius__factory.createInterface().encodeFunctionData('setUp', [encodedInitAzoriusData]); const azoriusSingleton = await new Azorius__factory(deployer).deploy(); @@ -288,37 +229,26 @@ describe("Atomic Gnosis Safe Deployment", () => { moduleProxyFactory, await azoriusSingleton.getAddress(), encodedSetupAzoriusData, - "10031021" + '10031021', ); // eslint-disable-next-line camelcase - const azoriusContract = Azorius__factory.connect( - predictedAzoriusModule, - deployer - ); + const azoriusContract = Azorius__factory.connect(predictedAzoriusModule, deployer); const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await azoriusSingleton.getAddress(), - encodedSetupAzoriusData, - "10031021", - ], + 'deployModule', + [await azoriusSingleton.getAddress(), encodedSetupAzoriusData, '10031021'], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); @@ -326,97 +256,80 @@ describe("Atomic Gnosis Safe Deployment", () => { const tx = await multiSendCallOnly.multiSend(safeTx); await expect(tx) - .to.emit(moduleProxyFactory, "ModuleProxyCreation") + .to.emit(moduleProxyFactory, 'ModuleProxyCreation') .withArgs(predictedAzoriusModule, await azoriusSingleton.getAddress()); expect(await azoriusContract.avatar()).eq(await gnosisSafe.getAddress()); - expect(await azoriusContract.getFunction("target")()).eq( - await gnosisSafe.getAddress() - ); + expect(await azoriusContract.getFunction('target')()).eq(await gnosisSafe.getAddress()); expect(await azoriusContract.owner()).eq(await gnosisSafe.getAddress()); }); - it("Setup Module w/ enabledModule event", async () => { + it('Setup Module w/ enabledModule event', async () => { const internalTxs: MetaTransaction[] = [ await buildContractCall( gnosisSafe, - "enableModule", + 'enableModule', [await fractalModule.getAddress()], 0, - false + false, ), ]; const safeInternalTx = encodeMultiSend(internalTxs); const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await fractalModuleSingleton.getAddress(), - setModuleCalldata, - "10031021", - ], + 'deployModule', + [await fractalModuleSingleton.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await freezeGuardImplementation.getAddress(), - freezeGuardFactoryInit, - "10031021", - ], + 'deployModule', + [await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, '10031021'], 0, - false + false, ), await buildContractCall( gnosisSafe, - "execTransaction", + 'execTransaction', [ await multiSendCallOnly.getAddress(), // to - "0", // value + '0', // value // eslint-disable-next-line camelcase - MultiSendCallOnly__factory.createInterface().encodeFunctionData( - "multiSend", - [safeInternalTx] - ), // calldata - "1", // operation - "0", // tx gas - "0", // base gas - "0", // gas price + MultiSendCallOnly__factory.createInterface().encodeFunctionData('multiSend', [ + safeInternalTx, + ]), // calldata + '1', // operation + '0', // tx gas + '0', // base gas + '0', // gas price ethers.ZeroAddress, // gas token ethers.ZeroAddress, // receiver sigs, // sigs ], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(gnosisSafe, "EnabledModule") + .to.emit(gnosisSafe, 'EnabledModule') .withArgs(await fractalModule.getAddress()); - expect( - await gnosisSafe.isModuleEnabled(await fractalModule.getAddress()) - ).to.eq(true); + expect(await gnosisSafe.isModuleEnabled(await fractalModule.getAddress())).to.eq(true); }); - it("Setup AzoriusModule w/ enabledModule event", async () => { + it('Setup AzoriusModule w/ enabledModule event', async () => { const VOTING_STRATEGIES_TO_DEPLOY: string[] = []; // @todo pass expected addresses for voting strategies const encodedInitAzoriusData = abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ await gnosisSafe.getAddress(), await gnosisSafe.getAddress(), @@ -424,13 +337,11 @@ describe("Atomic Gnosis Safe Deployment", () => { VOTING_STRATEGIES_TO_DEPLOY, 0, 0, - ] + ], ); const encodedSetupAzoriusData = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ - encodedInitAzoriusData, - ]); + Azorius__factory.createInterface().encodeFunctionData('setUp', [encodedInitAzoriusData]); const azoriusSingleton = await new Azorius__factory(deployer).deploy(); @@ -438,262 +349,206 @@ describe("Atomic Gnosis Safe Deployment", () => { moduleProxyFactory, await azoriusSingleton.getAddress(), encodedSetupAzoriusData, - "10031021" + '10031021', ); // eslint-disable-next-line camelcase - const azoriusContract = Azorius__factory.connect( - predictedAzoriusModule, - deployer - ); + const azoriusContract = Azorius__factory.connect(predictedAzoriusModule, deployer); const internalTxs: MetaTransaction[] = [ await buildContractCall( gnosisSafe, - "enableModule", + 'enableModule', [await fractalModule.getAddress()], 0, - false + false, ), await buildContractCall( gnosisSafe, - "enableModule", + 'enableModule', [await azoriusContract.getAddress()], 0, - false + false, ), ]; const safeInternalTx = encodeMultiSend(internalTxs); const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await fractalModuleSingleton.getAddress(), - setModuleCalldata, - "10031021", - ], + 'deployModule', + [await fractalModuleSingleton.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await freezeGuardImplementation.getAddress(), - freezeGuardFactoryInit, - "10031021", - ], + 'deployModule', + [await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await azoriusSingleton.getAddress(), - encodedSetupAzoriusData, - "10031021", - ], + 'deployModule', + [await azoriusSingleton.getAddress(), encodedSetupAzoriusData, '10031021'], 0, - false + false, ), await buildContractCall( gnosisSafe, - "execTransaction", + 'execTransaction', [ await multiSendCallOnly.getAddress(), // to - "0", // value + '0', // value // eslint-disable-next-line camelcase - MultiSendCallOnly__factory.createInterface().encodeFunctionData( - "multiSend", - [safeInternalTx] - ), // calldata - "1", // operation - "0", // tx gas - "0", // base gas - "0", // gas price + MultiSendCallOnly__factory.createInterface().encodeFunctionData('multiSend', [ + safeInternalTx, + ]), // calldata + '1', // operation + '0', // tx gas + '0', // base gas + '0', // gas price ethers.ZeroAddress, // gas token ethers.ZeroAddress, // receiver sigs, // sigs ], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(gnosisSafe, "EnabledModule") + .to.emit(gnosisSafe, 'EnabledModule') .withArgs(await azoriusContract.getAddress()); - expect( - await gnosisSafe.isModuleEnabled(await azoriusContract.getAddress()) - ).to.eq(true); + expect(await gnosisSafe.isModuleEnabled(await azoriusContract.getAddress())).to.eq(true); }); - it("Setup Guard w/ changeGuard event", async () => { + it('Setup Guard w/ changeGuard event', async () => { const internalTxs: MetaTransaction[] = [ - await buildContractCall( - gnosisSafe, - "setGuard", - [await freezeGuard.getAddress()], - 0, - false - ), + await buildContractCall(gnosisSafe, 'setGuard', [await freezeGuard.getAddress()], 0, false), ]; const safeInternalTx = encodeMultiSend(internalTxs); const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await fractalModuleSingleton.getAddress(), - setModuleCalldata, - "10031021", - ], + 'deployModule', + [await fractalModuleSingleton.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await freezeGuardImplementation.getAddress(), - freezeGuardFactoryInit, - "10031021", - ], + 'deployModule', + [await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, '10031021'], 0, - false + false, ), await buildContractCall( gnosisSafe, - "execTransaction", + 'execTransaction', [ await multiSendCallOnly.getAddress(), // to - "0", // value + '0', // value // eslint-disable-next-line camelcase - MultiSendCallOnly__factory.createInterface().encodeFunctionData( - "multiSend", - [safeInternalTx] - ), // calldata - "1", // operation - "0", // tx gas - "0", // base gas - "0", // gas price + MultiSendCallOnly__factory.createInterface().encodeFunctionData('multiSend', [ + safeInternalTx, + ]), // calldata + '1', // operation + '0', // tx gas + '0', // base gas + '0', // gas price ethers.ZeroAddress, // gas token ethers.ZeroAddress, // receiver sigs, // sigs ], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(gnosisSafe, "ChangedGuard") + .to.emit(gnosisSafe, 'ChangedGuard') .withArgs(await freezeGuard.getAddress()); }); - it("Setup Gnosis Safe w/ removedOwner event", async () => { + it('Setup Gnosis Safe w/ removedOwner event', async () => { const internalTxs: MetaTransaction[] = [ await buildContractCall( gnosisSafe, - "removeOwner", + 'removeOwner', [owner3.address, await multiSendCallOnly.getAddress(), threshold], 0, - false + false, ), ]; const safeInternalTx = encodeMultiSend(internalTxs); const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await fractalModuleSingleton.getAddress(), - setModuleCalldata, - "10031021", - ], + 'deployModule', + [await fractalModuleSingleton.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [ - await freezeGuardImplementation.getAddress(), - freezeGuardFactoryInit, - "10031021", - ], + 'deployModule', + [await freezeGuardImplementation.getAddress(), freezeGuardFactoryInit, '10031021'], 0, - false + false, ), await buildContractCall( gnosisSafe, - "execTransaction", + 'execTransaction', [ await multiSendCallOnly.getAddress(), // to - "0", // value + '0', // value // eslint-disable-next-line camelcase - MultiSendCallOnly__factory.createInterface().encodeFunctionData( - "multiSend", - [safeInternalTx] - ), // calldata - "1", // operation - "0", // tx gas - "0", // base gas - "0", // gas price + MultiSendCallOnly__factory.createInterface().encodeFunctionData('multiSend', [ + safeInternalTx, + ]), // calldata + '1', // operation + '0', // tx gas + '0', // base gas + '0', // gas price ethers.ZeroAddress, // gas token ethers.ZeroAddress, // receiver sigs, // sigs ], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(gnosisSafe, "RemovedOwner") + .to.emit(gnosisSafe, 'RemovedOwner') .withArgs(await multiSendCallOnly.getAddress()); expect(await gnosisSafe.isOwner(owner1.address)).eq(true); expect(await gnosisSafe.isOwner(owner2.address)).eq(true); expect(await gnosisSafe.isOwner(owner3.address)).eq(true); - expect(await gnosisSafe.isOwner(await multiSendCallOnly.getAddress())).eq( - false - ); + expect(await gnosisSafe.isOwner(await multiSendCallOnly.getAddress())).eq(false); expect(await gnosisSafe.getThreshold()).eq(threshold); }); }); diff --git a/test/Azorius-LinearERC20Voting.test.ts b/test/Azorius-LinearERC20Voting.test.ts index 8840f3b2..3abc55ec 100644 --- a/test/Azorius-LinearERC20Voting.test.ts +++ b/test/Azorius-LinearERC20Voting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { GnosisSafe, @@ -17,23 +15,23 @@ import { VotesERC20__factory, ModuleProxyFactory, GnosisSafeL2__factory, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; - -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; +import time from './time'; -describe("Safe with Azorius module and linearERC20Voting", () => { +describe('Safe with Azorius module and linearERC20Voting', () => { // Deployed contracts let gnosisSafe: GnosisSafe; let azorius: Azorius; @@ -58,9 +56,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Gnosis let createGnosisSetupCalldata: string; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); @@ -82,19 +78,19 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Get Gnosis Safe Proxy factory gnosisSafeProxyFactory = await hre.ethers.getContractAt( - "GnosisSafeProxyFactory", - await gnosisSafeProxyFactory.getAddress() + 'GnosisSafeProxyFactory', + await gnosisSafeProxyFactory.getAddress(), ); // Get module proxy factory moduleProxyFactory = await hre.ethers.getContractAt( - "ModuleProxyFactory", - await moduleProxyFactory.getAddress() + 'ModuleProxyFactory', + await moduleProxyFactory.getAddress(), ); createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [gnosisSafeOwner.address], 1, ethers.ZeroAddress, @@ -109,32 +105,29 @@ describe("Safe with Azorius module and linearERC20Voting", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, - saltNum + saltNum, ); - gnosisSafe = await hre.ethers.getContractAt( - "GnosisSafe", - predictedGnosisSafeAddress - ); + gnosisSafe = await hre.ethers.getContractAt('GnosisSafe', predictedGnosisSafeAddress); // Deploy Votes ERC-20 mastercopy contract votesERC20Mastercopy = await new VotesERC20__factory(deployer).deploy(); const votesERC20SetupCalldata = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "DCNT", - "DCNT", + 'DCNT', + 'DCNT', [ tokenHolder1.address, tokenHolder2.address, @@ -142,27 +135,24 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await gnosisSafe.getAddress(), ], [100, 200, 300, 600], - ] + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), votesERC20SetupCalldata, - "10031021" + '10031021', ); const predictedVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), votesERC20SetupCalldata, - "10031021" + '10031021', ); - votesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedVotesERC20Address - ); + votesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedVotesERC20Address); // Token holders delegate votes // Token holder 1 delegates to token holder 2, so final vote counts should be: @@ -178,9 +168,9 @@ describe("Safe with Azorius module and linearERC20Voting", () => { const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ gnosisSafeOwner.address, await gnosisSafe.getAddress(), @@ -188,46 +178,33 @@ describe("Safe with Azorius module and linearERC20Voting", () => { [], 60, // timelock period in blocks 60, // execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azorius = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azorius = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); // Deploy Linear ERC20 Voting Mastercopy - linearERC20VotingMastercopy = await new LinearERC20Voting__factory( - deployer - ).deploy(); + linearERC20VotingMastercopy = await new LinearERC20Voting__factory(deployer).deploy(); const linearERC20VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData("setUp", [ + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - [ - "address", - "address", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], + ['address', 'address', 'address', 'uint32', 'uint256', 'uint256', 'uint256'], [ gnosisSafeOwner.address, // owner await votesERC20.getAddress(), // governance token @@ -236,38 +213,35 @@ describe("Safe with Azorius module and linearERC20Voting", () => { 300, // proposer weight 500000, // quorom numerator, denominator is 1,000,000, so quorum percentage is 50% 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] + ], ), ]); await moduleProxyFactory.deployModule( await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); const predictedLinearERC20VotingAddress = await calculateProxyAddress( moduleProxyFactory, await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); linearERC20Voting = await hre.ethers.getContractAt( - "LinearERC20Voting", - predictedLinearERC20VotingAddress + 'LinearERC20Voting', + predictedLinearERC20VotingAddress, ); // Enable the Linear Voting strategy on Azorius - await azorius - .connect(gnosisSafeOwner) - .enableStrategy(await linearERC20Voting.getAddress()); + await azorius.connect(gnosisSafeOwner).enableStrategy(await linearERC20Voting.getAddress()); // Create transaction on Gnosis Safe to setup Azorius module - const enableAzoriusModuleData = gnosisSafe.interface.encodeFunctionData( - "enableModule", - [await azorius.getAddress()] - ); + const enableAzoriusModuleData = gnosisSafe.interface.encodeFunctionData('enableModule', [ + await azorius.getAddress(), + ]); const enableAzoriusModuleTx = buildSafeTransaction({ to: await gnosisSafe.getAddress(), @@ -276,13 +250,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { nonce: await gnosisSafe.nonce(), }); - const sigs = [ - await safeSignTypedData( - gnosisSafeOwner, - gnosisSafe, - enableAzoriusModuleTx - ), - ]; + const sigs = [await safeSignTypedData(gnosisSafeOwner, gnosisSafe, enableAzoriusModuleTx)]; const signatureBytes = buildSignatureBytes(sigs); @@ -298,67 +266,48 @@ describe("Safe with Azorius module and linearERC20Voting", () => { enableAzoriusModuleTx.gasPrice, enableAzoriusModuleTx.gasToken, enableAzoriusModuleTx.refundReceiver, - signatureBytes - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); // Gnosis Safe received the 1,000 tokens - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); }); - describe("Safe with Azorius module and linearERC20Voting", () => { - it("Gets correctly initialized", async () => { + describe('Safe with Azorius module and linearERC20Voting', () => { + it('Gets correctly initialized', async () => { expect(await linearERC20Voting.owner()).to.eq(gnosisSafeOwner.address); - expect(await linearERC20Voting.governanceToken()).to.eq( - await votesERC20.getAddress() - ); - expect(await linearERC20Voting.azoriusModule()).to.eq( - await azorius.getAddress() - ); + expect(await linearERC20Voting.governanceToken()).to.eq(await votesERC20.getAddress()); + expect(await linearERC20Voting.azoriusModule()).to.eq(await azorius.getAddress()); expect(await linearERC20Voting.votingPeriod()).to.eq(60); expect(await linearERC20Voting.quorumNumerator()).to.eq(500000); }); - it("A strategy cannot be enabled more than once", async () => { + it('A strategy cannot be enabled more than once', async () => { await expect( - azorius - .connect(gnosisSafeOwner) - .enableStrategy(await linearERC20Voting.getAddress()) - ).to.be.revertedWithCustomError(azorius, "StrategyEnabled()"); + azorius.connect(gnosisSafeOwner).enableStrategy(await linearERC20Voting.getAddress()), + ).to.be.revertedWithCustomError(azorius, 'StrategyEnabled()'); }); - it("An invalid strategy cannot be enabled", async () => { + it('An invalid strategy cannot be enabled', async () => { await expect( - azorius.connect(gnosisSafeOwner).enableStrategy(ethers.ZeroAddress) - ).to.be.revertedWithCustomError(azorius, "InvalidStrategy"); + azorius.connect(gnosisSafeOwner).enableStrategy(ethers.ZeroAddress), + ).to.be.revertedWithCustomError(azorius, 'InvalidStrategy'); }); - it("An invalid strategy cannot be disabled", async () => { + it('An invalid strategy cannot be disabled', async () => { await expect( - azorius - .connect(gnosisSafeOwner) - .disableStrategy(ethers.ZeroAddress, ethers.ZeroAddress) - ).to.be.revertedWithCustomError(azorius, "InvalidStrategy"); + azorius.connect(gnosisSafeOwner).disableStrategy(ethers.ZeroAddress, ethers.ZeroAddress), + ).to.be.revertedWithCustomError(azorius, 'InvalidStrategy'); }); - it("Multiple strategies can be enabled, disabled, and returned", async () => { - await azorius - .connect(gnosisSafeOwner) - .enableStrategy(mockStrategy1.address); + it('Multiple strategies can be enabled, disabled, and returned', async () => { + await azorius.connect(gnosisSafeOwner).enableStrategy(mockStrategy1.address); - await azorius - .connect(gnosisSafeOwner) - .enableStrategy(mockStrategy2.address); + await azorius.connect(gnosisSafeOwner).enableStrategy(mockStrategy2.address); expect( - ( - await azorius.getStrategies( - "0x0000000000000000000000000000000000000001", - 3 - ) - )._strategies + (await azorius.getStrategies('0x0000000000000000000000000000000000000001', 3))._strategies, ).to.deep.eq([ mockStrategy2.address, mockStrategy1.address, @@ -370,84 +319,72 @@ describe("Safe with Azorius module and linearERC20Voting", () => { .disableStrategy(mockStrategy2.address, mockStrategy1.address); expect( - ( - await azorius.getStrategies( - "0x0000000000000000000000000000000000000001", - 3 - ) - )._strategies - ).to.deep.eq([ - mockStrategy2.address, - await linearERC20Voting.getAddress(), - ]); + (await azorius.getStrategies('0x0000000000000000000000000000000000000001', 3))._strategies, + ).to.deep.eq([mockStrategy2.address, await linearERC20Voting.getAddress()]); }); - it("An invalid strategy cannot be disabled", async () => { + it('An invalid strategy cannot be disabled', async () => { await expect( - azorius - .connect(gnosisSafeOwner) - .disableStrategy(ethers.ZeroAddress, mockStrategy2.address) - ).to.be.revertedWithCustomError(azorius, "StrategyDisabled"); + azorius.connect(gnosisSafeOwner).disableStrategy(ethers.ZeroAddress, mockStrategy2.address), + ).to.be.revertedWithCustomError(azorius, 'StrategyDisabled'); }); - it("The owner can change the Azorius Module on the Strategy", async () => { - await linearERC20Voting - .connect(gnosisSafeOwner) - .setAzorius(deployer.address); + it('The owner can change the Azorius Module on the Strategy', async () => { + await linearERC20Voting.connect(gnosisSafeOwner).setAzorius(deployer.address); expect(await linearERC20Voting.azoriusModule()).to.eq(deployer.address); }); - it("A non-owner cannot change the Azorius Module on the Strategy", async () => { + it('A non-owner cannot change the Azorius Module on the Strategy', async () => { await expect( - linearERC20Voting.connect(tokenHolder1).setAzorius(deployer.address) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC20Voting.connect(tokenHolder1).setAzorius(deployer.address), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("The owner can update the voting period", async () => { + it('The owner can update the voting period', async () => { expect(await linearERC20Voting.votingPeriod()).to.eq(60); await linearERC20Voting.connect(gnosisSafeOwner).updateVotingPeriod(120); expect(await linearERC20Voting.votingPeriod()).to.eq(120); }); - it("A non-owner cannot update the strategy voting period", async () => { + it('A non-owner cannot update the strategy voting period', async () => { await expect( - linearERC20Voting.connect(tokenHolder1).updateVotingPeriod(120) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC20Voting.connect(tokenHolder1).updateVotingPeriod(120), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("The owner can update the timelock period", async () => { + it('The owner can update the timelock period', async () => { expect(await azorius.timelockPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateTimelockPeriod(120); expect(await azorius.timelockPeriod()).to.eq(120); }); - it("A non-owner cannot update the strategy timelock period", async () => { - await expect( - azorius.connect(tokenHolder1).updateTimelockPeriod(120) - ).to.be.revertedWith("Ownable: caller is not the owner"); + it('A non-owner cannot update the strategy timelock period', async () => { + await expect(azorius.connect(tokenHolder1).updateTimelockPeriod(120)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Getting proposal state on an invalid proposal ID reverts", async () => { + it('Getting proposal state on an invalid proposal ID reverts', async () => { await expect(azorius.proposalState(0)).to.be.revertedWithCustomError( azorius, - "InvalidProposal" + 'InvalidProposal', ); await expect(azorius.proposalState(0)).to.be.revertedWithCustomError( azorius, - "InvalidProposal" + 'InvalidProposal', ); }); - it("A proposal cannot be submitted if the specified strategy has not been enabled", async () => { + it('A proposal cannot be submitted if the specified strategy has not been enabled', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -460,35 +397,31 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await expect( azorius .connect(tokenHolder2) - .submitProposal( - await votesERC20.getAddress(), - "0x", - [proposalTransaction], - "" - ) - ).to.be.revertedWithCustomError(azorius, "StrategyDisabled"); + .submitProposal(await votesERC20.getAddress(), '0x', [proposalTransaction], ''), + ).to.be.revertedWithCustomError(azorius, 'StrategyDisabled'); }); - it("Proposal cannot be received by the strategy from address other than Azorius", async () => { + it('Proposal cannot be received by the strategy from address other than Azorius', async () => { // Submit call from address that isn't Azorius module - await expect( - linearERC20Voting.initializeProposal("0x") - ).to.be.revertedWithCustomError(linearERC20Voting, "OnlyAzorius"); + await expect(linearERC20Voting.initializeProposal('0x')).to.be.revertedWithCustomError( + linearERC20Voting, + 'OnlyAzorius', + ); }); it("Votes cannot be cast on a proposal that hasn't been submitted yet", async () => { // User attempts to vote on proposal that has not yet been submitted await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 1) - ).to.be.revertedWithCustomError(linearERC20Voting, "InvalidProposal"); + linearERC20Voting.connect(tokenHolder2).vote(0, 1), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidProposal'); }); - it("Votes cannot be cast after the voting period has ended", async () => { + it('Votes cannot be cast after the voting period has ended', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -499,12 +432,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -514,16 +442,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Users vote in support of proposal await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 1) - ).to.be.revertedWithCustomError(linearERC20Voting, "VotingEnded"); + linearERC20Voting.connect(tokenHolder2).vote(0, 1), + ).to.be.revertedWithCustomError(linearERC20Voting, 'VotingEnded'); }); - it("A voter cannot vote more than once on a proposal", async () => { + it('A voter cannot vote more than once on a proposal', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -534,12 +462,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -547,16 +470,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 1) - ).to.be.revertedWithCustomError(linearERC20Voting, "AlreadyVoted"); + linearERC20Voting.connect(tokenHolder2).vote(0, 1), + ).to.be.revertedWithCustomError(linearERC20Voting, 'AlreadyVoted'); }); - it("Correctly counts proposal Yes votes", async () => { + it('Correctly counts proposal Yes votes', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -567,14 +490,9 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -597,12 +515,12 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect((await linearERC20Voting.getProposalVotes(0)).yesVotes).to.eq(600); }); - it("Correctly counts proposal No votes", async () => { + it('Correctly counts proposal No votes', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -613,14 +531,9 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -643,12 +556,12 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect((await linearERC20Voting.getProposalVotes(0)).noVotes).to.eq(600); }); - it("Correctly counts proposal Abstain votes", async () => { + it('Correctly counts proposal Abstain votes', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -659,50 +572,37 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); - expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq( - 0 - ); + expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq(0); // Token holder 1 votes but does not have any voting weight await linearERC20Voting.connect(tokenHolder1).vote(0, 2); - expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq( - 0 - ); + expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq(0); // Token holder 2 votes with voting weight of 300 await linearERC20Voting.connect(tokenHolder2).vote(0, 2); - expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq( - 300 - ); + expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq(300); // Token holder 3 votes with voting weight of 300 await linearERC20Voting.connect(tokenHolder3).vote(0, 2); - expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq( - 600 - ); + expect((await linearERC20Voting.getProposalVotes(0)).abstainVotes).to.eq(600); }); - it("A proposal is passed with enough Yes votes and quorum", async () => { + it('A proposal is passed with enough Yes votes and quorum', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -713,12 +613,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -738,12 +633,12 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await expect(await azorius.proposalState(0)).to.eq(1); }); - it("A proposal is not passed if there are more No votes than Yes votes", async () => { + it('A proposal is not passed if there are more No votes than Yes votes', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -754,12 +649,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -779,22 +669,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect(await azorius.proposalState(0)).to.eq(5); await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); }); - it("A proposal is not passed if quorum is not reached", async () => { + it('A proposal is not passed if quorum is not reached', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -805,12 +689,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -826,25 +705,19 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await expect(await linearERC20Voting.isPassed(0)).to.be.false; await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); // Proposal in the failed state expect(await azorius.proposalState(0)).to.eq(5); }); - it("A proposal is not passed if voting period is not over", async () => { + it('A proposal is not passed if voting period is not over', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -855,12 +728,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -874,25 +742,19 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await expect(await linearERC20Voting.isPassed(0)).to.be.false; await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); }); - it("Submitting a proposal emits the event with the associated proposal metadata", async () => { + it('Submitting a proposal emits the event with the associated proposal metadata', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -901,44 +763,36 @@ describe("Safe with Azorius module and linearERC20Voting", () => { operation: 0, }; - const proposalMetadata = "This is my amazing proposal!"; + const proposalMetadata = 'This is my amazing proposal!'; const tx = await azorius .connect(tokenHolder2) .submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - proposalMetadata + proposalMetadata, ); const receipt = await hre.ethers.provider.getTransactionReceipt(tx.hash); const data = receipt!.logs[1].data; const topics = receipt!.logs[1].topics; - const event = azorius.interface.decodeEventLog( - "ProposalCreated", - data, - topics - ); + const event = azorius.interface.decodeEventLog('ProposalCreated', data, topics); // Check that the event emits the correct values expect(event.transactions[0].to).to.be.equal(proposalTransaction.to); - expect(event.transactions[0].value).to.be.equal( - proposalTransaction.value - ); + expect(event.transactions[0].value).to.be.equal(proposalTransaction.value); expect(event.transactions[0].data).to.be.equal(proposalTransaction.data); - expect(event.transactions[0].operation).to.be.equal( - proposalTransaction.operation - ); + expect(event.transactions[0].operation).to.be.equal(proposalTransaction.operation); expect(event.metadata).to.be.equal(proposalMetadata); }); - it("A proposal can be created and executed", async () => { + it('A proposal can be created and executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -949,18 +803,13 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); const txHash = await azorius.getTxHash( await votesERC20.getAddress(), 0n, tokenTransferData, - 0 + 0, ); const proposalTxHashes = await azorius.getProposalTxHashes(0); @@ -983,24 +832,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect(await azorius.proposalState(0)).to.eq(0); // Users haven't voted yet - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - false - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - false - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(false); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(false); // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await linearERC20Voting.connect(tokenHolder3).vote(0, 1); // Users have voted - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - true - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - true - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(true); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(true); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1014,9 +855,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -1025,7 +864,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { [await votesERC20.getAddress()], [0], [tokenTransferData], - [0] + [0], ); expect(await azorius.getProposal(0)).to.deep.eq([ @@ -1036,31 +875,29 @@ describe("Safe with Azorius module and linearERC20Voting", () => { 1, ]); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 0 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(600); // Proposal is in the executed state expect(await azorius.proposalState(0)).to.eq(3); }); - it("Multiple transactions can be executed from a single proposal", async () => { + it('Multiple transactions can be executed from a single proposal', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 100] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 100, + ]); - const tokenTransferData2 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 200] - ); + const tokenTransferData2 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 200, + ]); - const tokenTransferData3 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 300] - ); + const tokenTransferData3 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 300, + ]); const proposalTransaction1 = { to: await votesERC20.getAddress(), @@ -1087,9 +924,9 @@ describe("Safe with Azorius module and linearERC20Voting", () => { .connect(tokenHolder2) .submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1, proposalTransaction2, proposalTransaction3], - "" + '', ); // Proposal is active @@ -1111,9 +948,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -1126,24 +961,22 @@ describe("Safe with Azorius module and linearERC20Voting", () => { ], [0, 0, 0], [tokenTransferData1, tokenTransferData2, tokenTransferData3], - [0, 0, 0] + [0, 0, 0], ); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 0 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(600); // Proposal is executed expect(await azorius.proposalState(0)).to.eq(3); }); - it("Executing a proposal reverts if the transaction cannot be executed", async () => { + it('Executing a proposal reverts if the transaction cannot be executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 700] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 700, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1154,12 +987,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -1180,37 +1008,27 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "TxFailed"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData], [0]), + ).to.be.revertedWithCustomError(azorius, 'TxFailed'); // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); }); - it("If a proposal is not executed during the execution period, it becomes expired", async () => { + it('If a proposal is not executed during the execution period, it becomes expired', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1221,12 +1039,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -1255,20 +1068,14 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Execute the transaction await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); }); - it("A proposal with no transactions that passes goes immediately to executed", async () => { + it('A proposal with no transactions that passes goes immediately to executed', async () => { await azorius .connect(tokenHolder2) - .submitProposal(await linearERC20Voting.getAddress(), "0x", [], ""); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -1288,143 +1095,116 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await expect(await azorius.proposalState(0)).to.eq(3); }); - it("Only the owner can update the timelock period on Azorius", async () => { + it('Only the owner can update the timelock period on Azorius', async () => { expect(await azorius.timelockPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateTimelockPeriod(70); expect(await azorius.timelockPeriod()).to.eq(70); - await expect( - azorius.connect(tokenHolder1).updateTimelockPeriod(80) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(azorius.connect(tokenHolder1).updateTimelockPeriod(80)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the owner can update the execution period on Azorius", async () => { + it('Only the owner can update the execution period on Azorius', async () => { expect(await azorius.executionPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateExecutionPeriod(100); expect(await azorius.executionPeriod()).to.eq(100); - await expect( - azorius.connect(tokenHolder1).updateExecutionPeriod(110) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(azorius.connect(tokenHolder1).updateExecutionPeriod(110)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the owner can update the quorum numerator on the ERC20LinearVoting", async () => { + it('Only the owner can update the quorum numerator on the ERC20LinearVoting', async () => { expect(await linearERC20Voting.quorumNumerator()).to.eq(500000); - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateQuorumNumerator(600000); + await linearERC20Voting.connect(gnosisSafeOwner).updateQuorumNumerator(600000); expect(await linearERC20Voting.quorumNumerator()).to.eq(600000); await expect( - linearERC20Voting.connect(tokenHolder1).updateQuorumNumerator(700000) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC20Voting.connect(tokenHolder1).updateQuorumNumerator(700000), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Quorum numerator cannot be updated to a value larger than the denominator", async () => { + it('Quorum numerator cannot be updated to a value larger than the denominator', async () => { await expect( - linearERC20Voting - .connect(gnosisSafeOwner) - .updateQuorumNumerator(1000001) - ).to.be.revertedWithCustomError( - linearERC20Voting, - "InvalidQuorumNumerator" - ); + linearERC20Voting.connect(gnosisSafeOwner).updateQuorumNumerator(1000001), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidQuorumNumerator'); }); - it("Only the owner can update the basis numerator on the ERC20LinearVoting", async () => { + it('Only the owner can update the basis numerator on the ERC20LinearVoting', async () => { expect(await linearERC20Voting.basisNumerator()).to.eq(500000); - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateBasisNumerator(600000); + await linearERC20Voting.connect(gnosisSafeOwner).updateBasisNumerator(600000); expect(await linearERC20Voting.basisNumerator()).to.eq(600000); await expect( - linearERC20Voting.connect(tokenHolder1).updateBasisNumerator(700000) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC20Voting.connect(tokenHolder1).updateBasisNumerator(700000), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Basis numerator cannot be updated to a value larger than the denominator", async () => { + it('Basis numerator cannot be updated to a value larger than the denominator', async () => { await expect( - linearERC20Voting.connect(gnosisSafeOwner).updateBasisNumerator(1000001) - ).to.be.revertedWithCustomError( - linearERC20Voting, - "InvalidBasisNumerator" - ); + linearERC20Voting.connect(gnosisSafeOwner).updateBasisNumerator(1000001), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidBasisNumerator'); }); - it("Only the owner can update the proposer weight on the ERC20LinearVoting", async () => { + it('Only the owner can update the proposer weight on the ERC20LinearVoting', async () => { expect(await linearERC20Voting.requiredProposerWeight()).to.eq(300); - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateRequiredProposerWeight(1); + await linearERC20Voting.connect(gnosisSafeOwner).updateRequiredProposerWeight(1); expect(await linearERC20Voting.requiredProposerWeight()).to.eq(1); await expect( - linearERC20Voting.connect(tokenHolder1).updateRequiredProposerWeight(2) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC20Voting.connect(tokenHolder1).updateRequiredProposerWeight(2), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Linear ERC20 voting contract cannot be setup with an invalid governance token address", async () => { + it('Linear ERC20 voting contract cannot be setup with an invalid governance token address', async () => { const abiCoder = new ethers.AbiCoder(); // Deploy Linear ERC20 Voting Strategy - linearERC20Voting = await new LinearERC20Voting__factory( - deployer - ).deploy(); + linearERC20Voting = await new LinearERC20Voting__factory(deployer).deploy(); const linearERC20VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - [ - "address", - "address", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], - [ - gnosisSafeOwner.address, // owner - ethers.ZeroAddress, // governance token - await azorius.getAddress(), // Azorius module - 60, // voting period in blocks - 0, // proposer weight - 500000, // quorom numerator, denominator is 1,000,000, so quorum percentage is 50% - 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] - ), - ] - ); + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['address', 'address', 'address', 'uint32', 'uint256', 'uint256', 'uint256'], + [ + gnosisSafeOwner.address, // owner + ethers.ZeroAddress, // governance token + await azorius.getAddress(), // Azorius module + 60, // voting period in blocks + 0, // proposer weight + 500000, // quorom numerator, denominator is 1,000,000, so quorum percentage is 50% + 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) + ], + ), + ]); await expect( moduleProxyFactory.deployModule( await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" - ) + '10031021', + ), ).to.be.reverted; }); - it("An invalid vote type cannot be cast", async () => { + it('An invalid vote type cannot be cast', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1435,29 +1215,24 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // Users cast invalid vote types await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 3) - ).to.be.revertedWithCustomError(linearERC20Voting, "InvalidVote"); + linearERC20Voting.connect(tokenHolder2).vote(0, 3), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidVote'); await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 4) - ).to.be.revertedWithCustomError(linearERC20Voting, "InvalidVote"); + linearERC20Voting.connect(tokenHolder2).vote(0, 4), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidVote'); await expect( - linearERC20Voting.connect(tokenHolder2).vote(0, 5) - ).to.be.revertedWithCustomError(linearERC20Voting, "InvalidVote"); + linearERC20Voting.connect(tokenHolder2).vote(0, 5), + ).to.be.revertedWithCustomError(linearERC20Voting, 'InvalidVote'); }); - it("Azorius can be setup with multiple strategies", async () => { + it('Azorius can be setup with multiple strategies', async () => { const abiCoder = new ethers.AbiCoder(); // Deploy Azorius module @@ -1465,110 +1240,86 @@ describe("Safe with Azorius module and linearERC20Voting", () => { const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - [ - "address", - "address", - "address", - "address[]", - "uint256", - "uint256", - ], + ['address', 'address', 'address', 'address[]', 'uint256', 'uint256'], [ gnosisSafeOwner.address, await gnosisSafe.getAddress(), await gnosisSafe.getAddress(), - [ - tokenHolder1.address, - tokenHolder2.address, - tokenHolder3.address, - ], + [tokenHolder1.address, tokenHolder2.address, tokenHolder3.address], 60, // timelock period in blocks 60, // execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azorius = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azorius = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); expect(await azorius.isStrategyEnabled(tokenHolder1.address)).to.eq(true); expect(await azorius.isStrategyEnabled(tokenHolder2.address)).to.eq(true); expect(await azorius.isStrategyEnabled(tokenHolder3.address)).to.eq(true); }); - it("Only a valid proposer can submit proposals", async () => { + it('Only a valid proposer can submit proposals', async () => { const abiCoder = new ethers.AbiCoder(); // Deploy Mock Voting Strategy - const mockVotingStrategyMastercopy = - await new MockVotingStrategy__factory(deployer).deploy(); + const mockVotingStrategyMastercopy = await new MockVotingStrategy__factory(deployer).deploy(); const mockVotingStrategySetupCalldata = // eslint-disable-next-line camelcase - MockVotingStrategy__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["address"], - [ - tokenHolder1.address, // tokenHolder1 is the only valid proposer - ] - ), - ] - ); + MockVotingStrategy__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['address'], + [ + tokenHolder1.address, // tokenHolder1 is the only valid proposer + ], + ), + ]); await moduleProxyFactory.deployModule( await mockVotingStrategyMastercopy.getAddress(), mockVotingStrategySetupCalldata, - "10031021" + '10031021', ); const predictedMockVotingStrategyAddress = await calculateProxyAddress( moduleProxyFactory, await mockVotingStrategyMastercopy.getAddress(), mockVotingStrategySetupCalldata, - "10031021" + '10031021', ); mockVotingStrategy = await hre.ethers.getContractAt( - "MockVotingStrategy", - predictedMockVotingStrategyAddress + 'MockVotingStrategy', + predictedMockVotingStrategyAddress, ); // Enable the Mock Voting strategy on Azorius - await azorius - .connect(gnosisSafeOwner) - .enableStrategy(await mockVotingStrategy.getAddress()); + await azorius.connect(gnosisSafeOwner).enableStrategy(await mockVotingStrategy.getAddress()); - expect(await mockVotingStrategy.isProposer(tokenHolder1.address)).to.eq( - true - ); - expect(await mockVotingStrategy.isProposer(tokenHolder2.address)).to.eq( - false - ); + expect(await mockVotingStrategy.isProposer(tokenHolder1.address)).to.eq(true); + expect(await mockVotingStrategy.isProposer(tokenHolder2.address)).to.eq(false); // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1580,35 +1331,25 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // This user was setup as the proposer on the MockVotingStrategy, so should be able to submit a proposal await azorius .connect(tokenHolder1) - .submitProposal( - await mockVotingStrategy.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await mockVotingStrategy.getAddress(), '0x', [proposalTransaction], ''); // This user was not setup as the proposer, and so should not be able to submit a proposal await expect( azorius .connect(tokenHolder2) - .submitProposal( - await mockVotingStrategy.getAddress(), - "0x", - [proposalTransaction], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + .submitProposal(await mockVotingStrategy.getAddress(), '0x', [proposalTransaction], ''), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); expect(await mockVotingStrategy.isPassed(0)).to.eq(false); expect(await mockVotingStrategy.votingEndBlock(0)).to.eq(0); }); - it("A proposal cannot be executed if targets array length is zero", async () => { + it('A proposal cannot be executed if targets array length is zero', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1619,18 +1360,13 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); const txHash = await azorius.getTxHash( await votesERC20.getAddress(), 0n, tokenTransferData, - 0 + 0, ); const proposalTxHashes = await azorius.getProposalTxHashes(0); @@ -1653,24 +1389,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect(await azorius.proposalState(0)).to.eq(0); // Users haven't voted yet - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - false - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - false - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(false); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(false); // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await linearERC20Voting.connect(tokenHolder3).vote(0, 1); // Users have voted - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - true - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - true - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(true); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(true); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1684,23 +1412,22 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction - await expect( - azorius.executeProposal(0, [], [], [], []) - ).to.be.revertedWithCustomError(azorius, "InvalidTxs"); + await expect(azorius.executeProposal(0, [], [], [], [])).to.be.revertedWithCustomError( + azorius, + 'InvalidTxs', + ); }); - it("A proposal cannot be executed if unequal array lengths are passed", async () => { + it('A proposal cannot be executed if unequal array lengths are passed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1711,18 +1438,13 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); const txHash = await azorius.getTxHash( await votesERC20.getAddress(), 0n, tokenTransferData, - 0 + 0, ); const proposalTxHashes = await azorius.getProposalTxHashes(0); @@ -1745,24 +1467,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect(await azorius.proposalState(0)).to.eq(0); // Users haven't voted yet - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - false - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - false - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(false); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(false); // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await linearERC20Voting.connect(tokenHolder3).vote(0, 1); // Users have voted - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - true - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - true - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(true); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(true); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1776,23 +1490,21 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction await expect( - azorius.executeProposal(0, [await votesERC20.getAddress()], [], [], [0]) - ).to.be.revertedWithCustomError(azorius, "InvalidArrayLengths"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [], [], [0]), + ).to.be.revertedWithCustomError(azorius, 'InvalidArrayLengths'); }); - it("A proposal cannot be executed if too many TXs are passed to it", async () => { + it('A proposal cannot be executed if too many TXs are passed to it', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1803,18 +1515,13 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); const txHash = await azorius.getTxHash( await votesERC20.getAddress(), 0n, tokenTransferData, - 0 + 0, ); const proposalTxHashes = await azorius.getProposalTxHashes(0); @@ -1837,24 +1544,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { expect(await azorius.proposalState(0)).to.eq(0); // Users haven't voted yet - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - false - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - false - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(false); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(false); // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await linearERC20Voting.connect(tokenHolder3).vote(0, 1); // Users have voted - expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq( - true - ); - expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq( - true - ); + expect(await linearERC20Voting.hasVoted(0, tokenHolder2.address)).to.eq(true); + expect(await linearERC20Voting.hasVoted(0, tokenHolder3.address)).to.eq(true); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1868,9 +1567,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 600 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(600); expect(await votesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -1880,22 +1577,22 @@ describe("Safe with Azorius module and linearERC20Voting", () => { [await votesERC20.getAddress(), await votesERC20.getAddress()], [0, 0], [tokenTransferData, tokenTransferData], - [0, 0] - ) - ).to.be.revertedWithCustomError(azorius, "InvalidTxs"); + [0, 0], + ), + ).to.be.revertedWithCustomError(azorius, 'InvalidTxs'); }); - it("A proposal cannot be executed with the wrong TXs passed to it", async () => { + it('A proposal cannot be executed with the wrong TXs passed to it', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); - const tokenTransferData2 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 700] - ); + const tokenTransferData2 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 700, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1906,12 +1603,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); // Users vote in support of proposal await linearERC20Voting.connect(tokenHolder2).vote(0, 1); @@ -1928,22 +1620,16 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Execute the transaction await expect( - azorius.executeProposal( - 0, - [await votesERC20.getAddress()], - [0], - [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "InvalidTxHash"); + azorius.executeProposal(0, [await votesERC20.getAddress()], [0], [tokenTransferData2], [0]), + ).to.be.revertedWithCustomError(azorius, 'InvalidTxHash'); }); it("A non-proposer can't submit a proposal", async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -1952,60 +1638,39 @@ describe("Safe with Azorius module and linearERC20Voting", () => { operation: 0, }; - expect(await linearERC20Voting.isProposer(tokenHolder2.address)).to.eq( - true - ); + expect(await linearERC20Voting.isProposer(tokenHolder2.address)).to.eq(true); expect(await linearERC20Voting.isProposer(deployer.address)).to.eq(false); await expect( azorius .connect(deployer) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer()"); - - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateRequiredProposerWeight(301); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer()'); - expect(await linearERC20Voting.isProposer(tokenHolder2.address)).to.eq( - false - ); + await linearERC20Voting.connect(gnosisSafeOwner).updateRequiredProposerWeight(301); + + expect(await linearERC20Voting.isProposer(tokenHolder2.address)).to.eq(false); expect(await linearERC20Voting.isProposer(deployer.address)).to.eq(false); await expect( azorius .connect(deployer) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); await expect( azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); }); - it("isPassed logic is correct", async () => { + it('isPassed logic is correct', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 600] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 600, + ]); const proposalTransaction = { to: await votesERC20.getAddress(), @@ -2017,12 +1682,7 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Submit first proposal await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); await linearERC20Voting.connect(tokenHolder2).vote(0, 1); await linearERC20Voting.connect(tokenHolder3).vote(0, 2); @@ -2036,19 +1696,12 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Quorum and basis should be met expect(await linearERC20Voting.isPassed(0)).to.eq(true); - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateQuorumNumerator(600000); + await linearERC20Voting.connect(gnosisSafeOwner).updateQuorumNumerator(600000); // Submit second proposal await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); await linearERC20Voting.connect(tokenHolder2).vote(1, 1); await linearERC20Voting.connect(tokenHolder3).vote(1, 2); @@ -2063,19 +1716,12 @@ describe("Safe with Azorius module and linearERC20Voting", () => { // Only 50% of tokens have voted quorum should not be reached expect(await linearERC20Voting.isPassed(1)).to.eq(false); - await linearERC20Voting - .connect(gnosisSafeOwner) - .updateQuorumNumerator(250000); + await linearERC20Voting.connect(gnosisSafeOwner).updateQuorumNumerator(250000); // Submit third proposal await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC20Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC20Voting.getAddress(), '0x', [proposalTransaction], ''); await linearERC20Voting.connect(tokenHolder2).vote(2, 0); await linearERC20Voting.connect(tokenHolder3).vote(2, 1); diff --git a/test/Azorius-LinearERC721Voting.test.ts b/test/Azorius-LinearERC721Voting.test.ts index a55c6f9f..42d67ee8 100644 --- a/test/Azorius-LinearERC721Voting.test.ts +++ b/test/Azorius-LinearERC721Voting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { GnosisSafe, GnosisSafeProxyFactory, @@ -15,7 +13,13 @@ import { MockERC721__factory, MockContract__factory, GnosisSafeL2__factory, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, + getMockContract, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, @@ -24,15 +28,10 @@ import { calculateProxyAddress, mockTransaction, mockRevertTransaction, -} from "./helpers"; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, - getMockContract, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; +import time from './time'; -describe("Safe with Azorius module and linearERC721Voting", () => { +describe('Safe with Azorius module and linearERC721Voting', () => { const abiCoder = new ethers.AbiCoder(); // Deployed contracts @@ -70,14 +69,9 @@ describe("Safe with Azorius module and linearERC721Voting", () => { // Gnosis let createGnosisSetupCalldata: string; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); - async function mintNFT( - contract: MockERC721, - receiver: SignerWithAddress - ): Promise { + async function mintNFT(contract: MockERC721, receiver: SignerWithAddress): Promise { await contract.connect(receiver).mint(receiver.address); } @@ -86,27 +80,25 @@ describe("Safe with Azorius module and linearERC721Voting", () => { moduleProxyFactory = getModuleProxyFactory(); const gnosisSafeL2Singleton = getGnosisSafeL2Singleton(); - const abiCoder = new ethers.AbiCoder(); - // Get the signer accounts [deployer, gnosisSafeOwner, tokenHolder1, tokenHolder2, tokenHolder3] = await hre.ethers.getSigners(); // Get Gnosis Safe Proxy factory gnosisSafeProxyFactory = await hre.ethers.getContractAt( - "GnosisSafeProxyFactory", - await gnosisSafeProxyFactory.getAddress() + 'GnosisSafeProxyFactory', + await gnosisSafeProxyFactory.getAddress(), ); // Get module proxy factory moduleProxyFactory = await hre.ethers.getContractAt( - "ModuleProxyFactory", - await moduleProxyFactory.getAddress() + 'ModuleProxyFactory', + await moduleProxyFactory.getAddress(), ); createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [gnosisSafeOwner.address], 1, ethers.ZeroAddress, @@ -121,20 +113,17 @@ describe("Safe with Azorius module and linearERC721Voting", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, - saltNum + saltNum, ); - gnosisSafe = await hre.ethers.getContractAt( - "GnosisSafe", - predictedGnosisSafeAddress - ); + gnosisSafe = await hre.ethers.getContractAt('GnosisSafe', predictedGnosisSafeAddress); // Deploy Mock NFTs mockNFT1 = await new MockERC721__factory(deployer).deploy(); @@ -159,9 +148,7 @@ describe("Safe with Azorius module and linearERC721Voting", () => { holder2Ids = [0]; holder3Ids = [1, 1]; - mintNFTData = mockNFT1.interface.encodeFunctionData("mint", [ - deployer.address, - ]); + mintNFTData = mockNFT1.interface.encodeFunctionData('mint', [deployer.address]); proposalTransaction = { to: await mockNFT1.getAddress(), @@ -175,9 +162,9 @@ describe("Safe with Azorius module and linearERC721Voting", () => { const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ gnosisSafeOwner.address, await gnosisSafe.getAddress(), @@ -185,91 +172,80 @@ describe("Safe with Azorius module and linearERC721Voting", () => { [], 60, // timelock period in blocks 60, // execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azorius = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azorius = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); // Deploy Linear ERC721 Voting Mastercopy - linearERC721VotingMastercopy = await new LinearERC721Voting__factory( - deployer - ).deploy(); + linearERC721VotingMastercopy = await new LinearERC721Voting__factory(deployer).deploy(); const linearERC721VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC721Voting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - [ - "address", - "address[]", - "uint256[]", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], - [ - gnosisSafeOwner.address, // owner - [await mockNFT1.getAddress(), await mockNFT2.getAddress()], // NFT addresses - [1, 2], // NFT weights - await azorius.getAddress(), // Azorius module - 60, // voting period in blocks - 2, // quorom threshold - 2, // proposer threshold - 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] - ), - ] - ); + LinearERC721Voting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + [ + 'address', + 'address[]', + 'uint256[]', + 'address', + 'uint32', + 'uint256', + 'uint256', + 'uint256', + ], + [ + gnosisSafeOwner.address, // owner + [await mockNFT1.getAddress(), await mockNFT2.getAddress()], // NFT addresses + [1, 2], // NFT weights + await azorius.getAddress(), // Azorius module + 60, // voting period in blocks + 2, // quorom threshold + 2, // proposer threshold + 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) + ], + ), + ]); await moduleProxyFactory.deployModule( await linearERC721VotingMastercopy.getAddress(), linearERC721VotingSetupCalldata, - "10031021" + '10031021', ); const predictedlinearERC721VotingAddress = await calculateProxyAddress( moduleProxyFactory, await linearERC721VotingMastercopy.getAddress(), linearERC721VotingSetupCalldata, - "10031021" + '10031021', ); linearERC721Voting = await hre.ethers.getContractAt( - "LinearERC721Voting", - predictedlinearERC721VotingAddress + 'LinearERC721Voting', + predictedlinearERC721VotingAddress, ); // Enable the Linear Voting strategy on Azorius - await azorius - .connect(gnosisSafeOwner) - .enableStrategy(await linearERC721Voting.getAddress()); + await azorius.connect(gnosisSafeOwner).enableStrategy(await linearERC721Voting.getAddress()); // Create transaction on Gnosis Safe to setup Azorius module - const enableAzoriusModuleData = gnosisSafe.interface.encodeFunctionData( - "enableModule", - [await azorius.getAddress()] - ); + const enableAzoriusModuleData = gnosisSafe.interface.encodeFunctionData('enableModule', [ + await azorius.getAddress(), + ]); const enableAzoriusModuleTx = buildSafeTransaction({ to: await gnosisSafe.getAddress(), @@ -278,13 +254,7 @@ describe("Safe with Azorius module and linearERC721Voting", () => { nonce: await gnosisSafe.nonce(), }); - const sigs = [ - await safeSignTypedData( - gnosisSafeOwner, - gnosisSafe, - enableAzoriusModuleTx - ), - ]; + const sigs = [await safeSignTypedData(gnosisSafeOwner, gnosisSafe, enableAzoriusModuleTx)]; const signatureBytes = buildSignatureBytes(sigs); @@ -300,127 +270,106 @@ describe("Safe with Azorius module and linearERC721Voting", () => { enableAzoriusModuleTx.gasPrice, enableAzoriusModuleTx.gasToken, enableAzoriusModuleTx.refundReceiver, - signatureBytes - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - describe("Safe with Azorius module and linearERC721Voting", () => { - it("Gets correctly initialized", async () => { + describe('Safe with Azorius module and linearERC721Voting', () => { + it('Gets correctly initialized', async () => { expect(await linearERC721Voting.owner()).to.eq(gnosisSafeOwner.address); - expect(await linearERC721Voting.tokenAddresses(0)).to.eq( - await mockNFT1.getAddress() - ); - expect(await linearERC721Voting.tokenAddresses(1)).to.eq( - await mockNFT2.getAddress() - ); - expect(await linearERC721Voting.azoriusModule()).to.eq( - await azorius.getAddress() - ); + expect(await linearERC721Voting.tokenAddresses(0)).to.eq(await mockNFT1.getAddress()); + expect(await linearERC721Voting.tokenAddresses(1)).to.eq(await mockNFT2.getAddress()); + expect(await linearERC721Voting.azoriusModule()).to.eq(await azorius.getAddress()); expect(await linearERC721Voting.votingPeriod()).to.eq(60); expect(await linearERC721Voting.quorumThreshold()).to.eq(2); expect(await linearERC721Voting.proposerThreshold()).to.eq(2); }); - it("A strategy cannot be enabled more than once", async () => { + it('A strategy cannot be enabled more than once', async () => { await expect( - azorius - .connect(gnosisSafeOwner) - .enableStrategy(await linearERC721Voting.getAddress()) - ).to.be.revertedWithCustomError(azorius, "StrategyEnabled()"); + azorius.connect(gnosisSafeOwner).enableStrategy(await linearERC721Voting.getAddress()), + ).to.be.revertedWithCustomError(azorius, 'StrategyEnabled()'); }); - it("The owner can change the Azorius Module on the Strategy", async () => { - await linearERC721Voting - .connect(gnosisSafeOwner) - .setAzorius(deployer.address); + it('The owner can change the Azorius Module on the Strategy', async () => { + await linearERC721Voting.connect(gnosisSafeOwner).setAzorius(deployer.address); expect(await linearERC721Voting.azoriusModule()).to.eq(deployer.address); }); - it("A non-owner cannot change the Azorius Module on the Strategy", async () => { + it('A non-owner cannot change the Azorius Module on the Strategy', async () => { await expect( - linearERC721Voting.connect(tokenHolder1).setAzorius(deployer.address) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC721Voting.connect(tokenHolder1).setAzorius(deployer.address), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("The owner can update the voting period", async () => { + it('The owner can update the voting period', async () => { expect(await linearERC721Voting.votingPeriod()).to.eq(60); await linearERC721Voting.connect(gnosisSafeOwner).updateVotingPeriod(120); expect(await linearERC721Voting.votingPeriod()).to.eq(120); }); - it("A non-owner cannot update the strategy voting period", async () => { + it('A non-owner cannot update the strategy voting period', async () => { await expect( - linearERC721Voting.connect(tokenHolder1).updateVotingPeriod(120) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC721Voting.connect(tokenHolder1).updateVotingPeriod(120), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("The owner can update the timelock period", async () => { + it('The owner can update the timelock period', async () => { expect(await azorius.timelockPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateTimelockPeriod(120); expect(await azorius.timelockPeriod()).to.eq(120); }); - it("A non-owner cannot update the strategy timelock period", async () => { - await expect( - azorius.connect(tokenHolder1).updateTimelockPeriod(120) - ).to.be.revertedWith("Ownable: caller is not the owner"); + it('A non-owner cannot update the strategy timelock period', async () => { + await expect(azorius.connect(tokenHolder1).updateTimelockPeriod(120)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Getting proposal state on an invalid proposal ID reverts", async () => { + it('Getting proposal state on an invalid proposal ID reverts', async () => { await expect(azorius.proposalState(0)).to.be.revertedWithCustomError( azorius, - "InvalidProposal" + 'InvalidProposal', ); await expect(azorius.proposalState(0)).to.be.revertedWithCustomError( azorius, - "InvalidProposal" + 'InvalidProposal', ); }); - it("A proposal cannot be submitted if the specified strategy has not been enabled", async () => { + it('A proposal cannot be submitted if the specified strategy has not been enabled', async () => { // Use an incorrect address for the strategy await expect( azorius .connect(tokenHolder2) - .submitProposal( - await mockNFT1.getAddress(), - "0x", - [await mockTransaction()], - "" - ) - ).to.be.revertedWithCustomError(azorius, "StrategyDisabled"); + .submitProposal(await mockNFT1.getAddress(), '0x', [await mockTransaction()], ''), + ).to.be.revertedWithCustomError(azorius, 'StrategyDisabled'); }); - it("Proposal cannot be received by the strategy from address other than Azorius", async () => { + it('Proposal cannot be received by the strategy from address other than Azorius', async () => { // Submit call from address that isn't Azorius module - await expect( - linearERC721Voting.initializeProposal("0x") - ).to.be.revertedWithCustomError(linearERC721Voting, "OnlyAzorius"); + await expect(linearERC721Voting.initializeProposal('0x')).to.be.revertedWithCustomError( + linearERC721Voting, + 'OnlyAzorius', + ); }); it("Votes cannot be cast on a proposal that hasn't been submitted yet", async () => { // User attempts to vote on proposal that has not yet been submitted await expect( - linearERC721Voting - .connect(tokenHolder1) - .vote(0, 1, holder1Tokens, holder1Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "InvalidProposal"); + linearERC721Voting.connect(tokenHolder1).vote(0, 1, holder1Tokens, holder1Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'InvalidProposal'); }); - it("Votes cannot be cast after the voting period has ended", async () => { + it('Votes cannot be cast after the voting period has ended', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -430,75 +379,50 @@ describe("Safe with Azorius module and linearERC721Voting", () => { // Users vote in support of proposal await expect( - linearERC721Voting - .connect(tokenHolder1) - .vote(0, 1, holder1Tokens, holder1Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "VotingEnded"); + linearERC721Voting.connect(tokenHolder1).vote(0, 1, holder1Tokens, holder1Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'VotingEnded'); }); - it("A voter cannot vote more than once on a proposal with the same id", async () => { + it('A voter cannot vote more than once on a proposal with the same id', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // User votes in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); // User votes again await expect( - linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "IdAlreadyVoted"); + linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'IdAlreadyVoted'); }); - it("A voter can vote more than once with different ids", async () => { + it('A voter can vote more than once with different ids', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // User votes in support of proposal - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, [await mockNFT1.getAddress()], [1]); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, [await mockNFT1.getAddress()], [1]); // User votes again - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, [await mockNFT2.getAddress()], [1]); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, [await mockNFT2.getAddress()], [1]); expect((await linearERC721Voting.getProposalVotes(0)).yesVotes).to.eq(3); }); - it("Correctly counts proposal Yes votes", async () => { + it('Correctly counts proposal Yes votes', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -506,38 +430,27 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect((await linearERC721Voting.getProposalVotes(0)).yesVotes).to.eq(0); // Token holder 1 votes with voting weight of 1 - await linearERC721Voting - .connect(tokenHolder1) - .vote(0, 1, holder1Tokens, holder1Ids); + await linearERC721Voting.connect(tokenHolder1).vote(0, 1, holder1Tokens, holder1Ids); expect((await linearERC721Voting.getProposalVotes(0)).yesVotes).to.eq(1); // Token holder 2 votes with voting weight of 2 - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); expect((await linearERC721Voting.getProposalVotes(0)).yesVotes).to.eq(3); // Token holder 3 votes with voting weight of 3 - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); expect((await linearERC721Voting.getProposalVotes(0)).yesVotes).to.eq(6); }); - it("Correctly counts proposal No votes", async () => { + it('Correctly counts proposal No votes', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -545,83 +458,53 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect((await linearERC721Voting.getProposalVotes(0)).noVotes).to.eq(0); // Token holder 1 votes with voting weight of 1 - await linearERC721Voting - .connect(tokenHolder1) - .vote(0, 0, holder1Tokens, holder1Ids); + await linearERC721Voting.connect(tokenHolder1).vote(0, 0, holder1Tokens, holder1Ids); expect((await linearERC721Voting.getProposalVotes(0)).noVotes).to.eq(1); // Token holder 2 votes with voting weight of 2 - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 0, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 0, holder2Tokens, holder2Ids); expect((await linearERC721Voting.getProposalVotes(0)).noVotes).to.eq(3); // Token holder 3 votes with voting weight of 3 - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 0, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 0, holder3Tokens, holder3Ids); expect((await linearERC721Voting.getProposalVotes(0)).noVotes).to.eq(6); }); - it("Correctly counts proposal Abstain votes", async () => { + it('Correctly counts proposal Abstain votes', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); - expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq( - 0 - ); + expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq(0); // Token holder 1 votes with voting weight of 1 - await linearERC721Voting - .connect(tokenHolder1) - .vote(0, 2, holder1Tokens, holder1Ids); + await linearERC721Voting.connect(tokenHolder1).vote(0, 2, holder1Tokens, holder1Ids); - expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq( - 1 - ); + expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq(1); // Token holder 2 votes with voting weight of 2 - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 2, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 2, holder2Tokens, holder2Ids); - expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq( - 3 - ); + expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq(3); // Token holder 3 votes with voting weight of 3 - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 2, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 2, holder3Tokens, holder3Ids); - expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq( - 6 - ); + expect((await linearERC721Voting.getProposalVotes(0)).abstainVotes).to.eq(6); }); - it("A proposal is passed with enough Yes votes and quorum", async () => { + it('A proposal is passed with enough Yes votes and quorum', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -629,12 +512,8 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -645,15 +524,10 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await azorius.proposalState(0)).to.eq(1); }); - it("A proposal is not passed if there are more No votes than Yes votes", async () => { + it('A proposal is not passed if there are more No votes than Yes votes', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -661,12 +535,8 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; // Users vote against - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 0, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 0, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 0, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 0, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -677,25 +547,14 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect(await azorius.proposalState(0)).to.eq(5); await expect( - azorius.executeProposal( - 0, - [await mockNFT1.getAddress()], - [0], - [mintNFTData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await mockNFT1.getAddress()], [0], [mintNFTData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); }); - it("A proposal is not passed if quorum is not reached", async () => { + it('A proposal is not passed if quorum is not reached', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -703,9 +562,7 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; // User votes "Yes" - await linearERC721Voting - .connect(tokenHolder1) - .vote(0, 1, holder1Tokens, holder1Ids); + await linearERC721Voting.connect(tokenHolder1).vote(0, 1, holder1Tokens, holder1Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -713,28 +570,17 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; await expect( - azorius.executeProposal( - 0, - [await mockNFT1.getAddress()], - [0], - [mintNFTData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await mockNFT1.getAddress()], [0], [mintNFTData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); // Proposal in the failed state expect(await azorius.proposalState(0)).to.eq(5); }); - it("A proposal is not passed if voting period is not over", async () => { + it('A proposal is not passed if voting period is not over', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -742,78 +588,50 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; // Users vote "Yes" - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); await expect(await linearERC721Voting.isPassed(0)).to.be.false; await expect( - azorius.executeProposal( - 0, - [await mockNFT1.getAddress()], - [0], - [mintNFTData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await mockNFT1.getAddress()], [0], [mintNFTData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); }); - it("Submitting a proposal emits the event with the associated proposal metadata", async () => { - const proposalMetadata = "This is my amazing proposal!"; + it('Submitting a proposal emits the event with the associated proposal metadata', async () => { + const proposalMetadata = 'This is my amazing proposal!'; const tx = await azorius .connect(tokenHolder2) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - proposalMetadata + proposalMetadata, ); const receipt = await hre.ethers.provider.getTransactionReceipt(tx.hash); const data = receipt!.logs[1].data; const topics = receipt!.logs[1].topics; - const event = azorius.interface.decodeEventLog( - "ProposalCreated", - data, - topics - ); + const event = azorius.interface.decodeEventLog('ProposalCreated', data, topics); // Check that the event emits the correct values expect(event.transactions[0].to).to.be.equal(proposalTransaction.to); - expect(event.transactions[0].value).to.be.equal( - proposalTransaction.value - ); + expect(event.transactions[0].value).to.be.equal(proposalTransaction.value); expect(event.transactions[0].data).to.be.equal(proposalTransaction.data); - expect(event.transactions[0].operation).to.be.equal( - proposalTransaction.operation - ); + expect(event.transactions[0].operation).to.be.equal(proposalTransaction.operation); expect(event.metadata).to.be.equal(proposalMetadata); }); - it("A proposal can be created and executed", async () => { + it('A proposal can be created and executed', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [proposalTransaction], ''); - const txHash = await azorius.getTxHash( - await mockNFT1.getAddress(), - 0n, - mintNFTData, - 0 - ); + const txHash = await azorius.getTxHash(await mockNFT1.getAddress(), 0n, mintNFTData, 0); const proposalTxHashes = await azorius.getProposalTxHashes(0); @@ -835,29 +653,17 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect(await azorius.proposalState(0)).to.eq(0); // NFT ids haven't voted yet - expect( - await linearERC721Voting.hasVoted(0, await mockNFT1.getAddress(), 0) - ).to.eq(false); - expect( - await linearERC721Voting.hasVoted(0, await mockNFT2.getAddress(), 0) - ).to.eq(false); + expect(await linearERC721Voting.hasVoted(0, await mockNFT1.getAddress(), 0)).to.eq(false); + expect(await linearERC721Voting.hasVoted(0, await mockNFT2.getAddress(), 0)).to.eq(false); // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder1) - .vote(0, 1, holder1Tokens, holder1Ids); + await linearERC721Voting.connect(tokenHolder1).vote(0, 1, holder1Tokens, holder1Ids); - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); // NFT ids have voted - expect( - await linearERC721Voting.hasVoted(0, await mockNFT1.getAddress(), 0) - ).to.eq(true); - expect( - await linearERC721Voting.hasVoted(0, await mockNFT2.getAddress(), 0) - ).to.eq(true); + expect(await linearERC721Voting.hasVoted(0, await mockNFT1.getAddress(), 0)).to.eq(true); + expect(await linearERC721Voting.hasVoted(0, await mockNFT2.getAddress(), 0)).to.eq(true); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -874,13 +680,7 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect(await mockNFT1.balanceOf(deployer.address)).to.eq(0); // Execute the transaction - await azorius.executeProposal( - 0, - [await mockNFT1.getAddress()], - [0], - [mintNFTData], - [0] - ); + await azorius.executeProposal(0, [await mockNFT1.getAddress()], [0], [mintNFTData], [0]); expect(await azorius.getProposal(0)).to.deep.eq([ await linearERC721Voting.getAddress(), @@ -896,7 +696,7 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect(await azorius.proposalState(0)).to.eq(3); }); - it("Multiple transactions can be executed from a single proposal", async () => { + it('Multiple transactions can be executed from a single proposal', async () => { // Create transaction to mint tokens to the deployer const tokenTransferData1 = mintNFTData; const tokenTransferData2 = mintNFTData; @@ -927,21 +727,17 @@ describe("Safe with Azorius module and linearERC721Voting", () => { .connect(tokenHolder2) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [proposalTransaction1, proposalTransaction2, proposalTransaction3], - "" + '', ); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -960,14 +756,10 @@ describe("Safe with Azorius module and linearERC721Voting", () => { // Execute the transaction await azorius.executeProposal( 0, - [ - await mockNFT1.getAddress(), - await mockNFT1.getAddress(), - await mockNFT1.getAddress(), - ], + [await mockNFT1.getAddress(), await mockNFT1.getAddress(), await mockNFT1.getAddress()], [0, 0, 0], [tokenTransferData1, tokenTransferData2, tokenTransferData3], - [0, 0, 0] + [0, 0, 0], ); expect(await mockNFT1.balanceOf(deployer.address)).to.eq(3); @@ -976,26 +768,22 @@ describe("Safe with Azorius module and linearERC721Voting", () => { expect(await azorius.proposalState(0)).to.eq(3); }); - it("Executing a proposal reverts if the transaction cannot be executed", async () => { + it('Executing a proposal reverts if the transaction cannot be executed', async () => { await azorius .connect(tokenHolder2) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [await mockRevertTransaction()], - "" + '', ); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1017,38 +805,27 @@ describe("Safe with Azorius module and linearERC721Voting", () => { [0], [ // eslint-disable-next-line camelcase - MockContract__factory.createInterface().encodeFunctionData( - "revertSomething" - ), + MockContract__factory.createInterface().encodeFunctionData('revertSomething'), ], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "TxFailed"); + [0], + ), + ).to.be.revertedWithCustomError(azorius, 'TxFailed'); // Proposal is executable expect(await azorius.proposalState(0)).to.eq(2); }); - it("If a proposal is not executed during the execution period, it becomes expired", async () => { + it('If a proposal is not executed during the execution period, it becomes expired', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [proposalTransaction], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [proposalTransaction], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1070,20 +847,14 @@ describe("Safe with Azorius module and linearERC721Voting", () => { // Execute the transaction await expect( - azorius.executeProposal( - 0, - [await mockNFT1.getAddress()], - [0], - [mintNFTData], - [0] - ) - ).to.be.revertedWithCustomError(azorius, "ProposalNotExecutable"); + azorius.executeProposal(0, [await mockNFT1.getAddress()], [0], [mintNFTData], [0]), + ).to.be.revertedWithCustomError(azorius, 'ProposalNotExecutable'); }); - it("A proposal with no transactions that passes goes immediately to executed", async () => { + it('A proposal with no transactions that passes goes immediately to executed', async () => { await azorius .connect(tokenHolder2) - .submitProposal(await linearERC721Voting.getAddress(), "0x", [], ""); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); @@ -1091,12 +862,8 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await linearERC721Voting.isPassed(0)).to.be.false; // Users vote in support of proposal - await linearERC721Voting - .connect(tokenHolder2) - .vote(0, 1, holder2Tokens, holder2Ids); - await linearERC721Voting - .connect(tokenHolder3) - .vote(0, 1, holder3Tokens, holder3Ids); + await linearERC721Voting.connect(tokenHolder2).vote(0, 1, holder2Tokens, holder2Ids); + await linearERC721Voting.connect(tokenHolder3).vote(0, 1, holder3Tokens, holder3Ids); // Increase time so that voting period has ended await time.advanceBlocks(60); @@ -1107,210 +874,173 @@ describe("Safe with Azorius module and linearERC721Voting", () => { await expect(await azorius.proposalState(0)).to.eq(3); }); - it("Only the owner can update the timelock period on Azorius", async () => { + it('Only the owner can update the timelock period on Azorius', async () => { expect(await azorius.timelockPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateTimelockPeriod(70); expect(await azorius.timelockPeriod()).to.eq(70); - await expect( - azorius.connect(tokenHolder1).updateTimelockPeriod(80) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(azorius.connect(tokenHolder1).updateTimelockPeriod(80)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the owner can update the execution period on Azorius", async () => { + it('Only the owner can update the execution period on Azorius', async () => { expect(await azorius.executionPeriod()).to.eq(60); await azorius.connect(gnosisSafeOwner).updateExecutionPeriod(100); expect(await azorius.executionPeriod()).to.eq(100); - await expect( - azorius.connect(tokenHolder1).updateExecutionPeriod(110) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(azorius.connect(tokenHolder1).updateExecutionPeriod(110)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the owner can update the quorum threshold on the ERC721LinearVoting", async () => { + it('Only the owner can update the quorum threshold on the ERC721LinearVoting', async () => { expect(await linearERC721Voting.quorumThreshold()).to.eq(2); - await linearERC721Voting - .connect(gnosisSafeOwner) - .updateQuorumThreshold(4); + await linearERC721Voting.connect(gnosisSafeOwner).updateQuorumThreshold(4); expect(await linearERC721Voting.quorumThreshold()).to.eq(4); await expect( - linearERC721Voting.connect(tokenHolder1).updateQuorumThreshold(5) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC721Voting.connect(tokenHolder1).updateQuorumThreshold(5), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Only the owner can update the basis numerator on the ERC721LinearVoting", async () => { + it('Only the owner can update the basis numerator on the ERC721LinearVoting', async () => { expect(await linearERC721Voting.basisNumerator()).to.eq(500000); - await linearERC721Voting - .connect(gnosisSafeOwner) - .updateBasisNumerator(600000); + await linearERC721Voting.connect(gnosisSafeOwner).updateBasisNumerator(600000); expect(await linearERC721Voting.basisNumerator()).to.eq(600000); await expect( - linearERC721Voting.connect(tokenHolder1).updateBasisNumerator(700000) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC721Voting.connect(tokenHolder1).updateBasisNumerator(700000), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Basis numerator cannot be updated to a value larger than the denominator", async () => { + it('Basis numerator cannot be updated to a value larger than the denominator', async () => { await expect( - linearERC721Voting - .connect(gnosisSafeOwner) - .updateBasisNumerator(1000001) - ).to.be.revertedWithCustomError( - linearERC721Voting, - "InvalidBasisNumerator" - ); + linearERC721Voting.connect(gnosisSafeOwner).updateBasisNumerator(1000001), + ).to.be.revertedWithCustomError(linearERC721Voting, 'InvalidBasisNumerator'); }); - it("Only the owner can update the proposer weight on the ERC721LinearVoting", async () => { + it('Only the owner can update the proposer weight on the ERC721LinearVoting', async () => { expect(await linearERC721Voting.proposerThreshold()).to.eq(2); - await linearERC721Voting - .connect(gnosisSafeOwner) - .updateProposerThreshold(2); + await linearERC721Voting.connect(gnosisSafeOwner).updateProposerThreshold(2); expect(await linearERC721Voting.proposerThreshold()).to.eq(2); await expect( - linearERC721Voting.connect(tokenHolder1).updateProposerThreshold(3) - ).to.be.revertedWith("Ownable: caller is not the owner"); + linearERC721Voting.connect(tokenHolder1).updateProposerThreshold(3), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Linear ERC721 voting contract cannot be setup with an invalid governance token address", async () => { + it('Linear ERC721 voting contract cannot be setup with an invalid governance token address', async () => { // Deploy Linear ERC721 Voting Strategy - linearERC721Voting = await new LinearERC721Voting__factory( - deployer - ).deploy(); + linearERC721Voting = await new LinearERC721Voting__factory(deployer).deploy(); const linearERC721VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC721Voting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - [ - "address", - "address[]", - "uint256[]", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], - [ - gnosisSafeOwner.address, // owner - [ethers.ZeroAddress], // NFT addresses - [1], // NFT weights - await azorius.getAddress(), // Azorius module - 60, // voting period in blocks - 1, // quorom threshold - 1, // proposer threshold - 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] - ), - ] - ); + LinearERC721Voting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + [ + 'address', + 'address[]', + 'uint256[]', + 'address', + 'uint32', + 'uint256', + 'uint256', + 'uint256', + ], + [ + gnosisSafeOwner.address, // owner + [ethers.ZeroAddress], // NFT addresses + [1], // NFT weights + await azorius.getAddress(), // Azorius module + 60, // voting period in blocks + 1, // quorom threshold + 1, // proposer threshold + 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) + ], + ), + ]); await expect( moduleProxyFactory.deployModule( await linearERC721VotingMastercopy.getAddress(), linearERC721VotingSetupCalldata, - "10031021" - ) + '10031021', + ), ).to.be.reverted; }); - it("An invalid vote type cannot be cast", async () => { + it('An invalid vote type cannot be cast', async () => { await azorius .connect(tokenHolder2) - .submitProposal( - await linearERC721Voting.getAddress(), - "0x", - [await mockTransaction()], - "" - ); + .submitProposal(await linearERC721Voting.getAddress(), '0x', [await mockTransaction()], ''); // Proposal is active expect(await azorius.proposalState(0)).to.eq(0); // Users cast invalid vote types await expect( - linearERC721Voting - .connect(tokenHolder2) - .vote(0, 3, holder2Tokens, holder2Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "InvalidVote"); + linearERC721Voting.connect(tokenHolder2).vote(0, 3, holder2Tokens, holder2Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'InvalidVote'); await expect( - linearERC721Voting - .connect(tokenHolder2) - .vote(0, 4, holder2Tokens, holder2Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "InvalidVote"); + linearERC721Voting.connect(tokenHolder2).vote(0, 4, holder2Tokens, holder2Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'InvalidVote'); await expect( - linearERC721Voting - .connect(tokenHolder2) - .vote(0, 5, holder2Tokens, holder2Ids) - ).to.be.revertedWithCustomError(linearERC721Voting, "InvalidVote"); + linearERC721Voting.connect(tokenHolder2).vote(0, 5, holder2Tokens, holder2Ids), + ).to.be.revertedWithCustomError(linearERC721Voting, 'InvalidVote'); }); it("A non-proposer can't submit a proposal", async () => { - expect(await linearERC721Voting.isProposer(tokenHolder2.address)).to.eq( - true - ); - expect(await linearERC721Voting.isProposer(deployer.address)).to.eq( - false - ); + expect(await linearERC721Voting.isProposer(tokenHolder2.address)).to.eq(true); + expect(await linearERC721Voting.isProposer(deployer.address)).to.eq(false); await expect( azorius .connect(deployer) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [await mockTransaction()], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + '', + ), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); - await linearERC721Voting - .connect(gnosisSafeOwner) - .updateProposerThreshold(301); + await linearERC721Voting.connect(gnosisSafeOwner).updateProposerThreshold(301); - expect(await linearERC721Voting.isProposer(tokenHolder2.address)).to.eq( - false - ); - expect(await linearERC721Voting.isProposer(deployer.address)).to.eq( - false - ); + expect(await linearERC721Voting.isProposer(tokenHolder2.address)).to.eq(false); + expect(await linearERC721Voting.isProposer(deployer.address)).to.eq(false); await expect( azorius .connect(deployer) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [await mockTransaction()], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + '', + ), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); await expect( azorius .connect(tokenHolder2) .submitProposal( await linearERC721Voting.getAddress(), - "0x", + '0x', [await mockTransaction()], - "" - ) - ).to.be.revertedWithCustomError(azorius, "InvalidProposer"); + '', + ), + ).to.be.revertedWithCustomError(azorius, 'InvalidProposer'); }); it("An proposal that hasn't been submitted yet is not passed", async () => { diff --git a/test/AzoriusFreezeGuard-ERC20FreezeVoting.test.ts b/test/AzoriusFreezeGuard-ERC20FreezeVoting.test.ts index cce6dd60..38a13082 100644 --- a/test/AzoriusFreezeGuard-ERC20FreezeVoting.test.ts +++ b/test/AzoriusFreezeGuard-ERC20FreezeVoting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { GnosisSafe, @@ -19,23 +17,24 @@ import { VotesERC20__factory, ModuleProxyFactory, GnosisSafeL2__factory, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; +} from './helpers'; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +import time from './time'; -describe("Azorius Child DAO with Azorius Parent", () => { +describe('Azorius Child DAO with Azorius Parent', () => { // Deployed contracts let childGnosisSafe: GnosisSafe; let freezeGuardMastercopy: AzoriusFreezeGuard; @@ -64,9 +63,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Gnosis let createGnosisSetupCalldata: string; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); @@ -88,7 +85,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [childSafeOwner.address], 1, ethers.ZeroAddress, @@ -103,123 +100,109 @@ describe("Azorius Child DAO with Azorius Parent", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, - saltNum + saltNum, ); // Get module proxy factory moduleProxyFactory = await hre.ethers.getContractAt( - "ModuleProxyFactory", - await moduleProxyFactory.getAddress() + 'ModuleProxyFactory', + await moduleProxyFactory.getAddress(), ); - childGnosisSafe = await hre.ethers.getContractAt( - "GnosisSafe", - predictedGnosisSafeAddress - ); + childGnosisSafe = await hre.ethers.getContractAt('GnosisSafe', predictedGnosisSafeAddress); // Deploy Votes ERC20 Mastercopy votesERC20Mastercopy = await new VotesERC20__factory(deployer).deploy(); const childVotesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "CHILD", - "CHILD", + 'CHILD', + 'CHILD', [ childTokenHolder1.address, childTokenHolder2.address, await childGnosisSafe.getAddress(), ], [100, 100, 100], - ] + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), childVotesERC20SetupData, - "10031021" + '10031021', ); const predictedChildVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), childVotesERC20SetupData, - "10031021" + '10031021', ); - childVotesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedChildVotesERC20Address - ); + childVotesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedChildVotesERC20Address); // Parent Votes ERC-20 parentVotesERC20 = await new VotesERC20__factory(deployer).deploy(); const parentVotesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "PARENT", - "PARENT", + 'PARENT', + 'PARENT', [parentTokenHolder1.address, parentTokenHolder2.address], [100, 100], - ] + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), parentVotesERC20SetupData, - "10031021" + '10031021', ); const predictedParentVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), parentVotesERC20SetupData, - "10031021" + '10031021', ); parentVotesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedParentVotesERC20Address + 'VotesERC20', + predictedParentVotesERC20Address, ); // Token holders delegate their votes to themselves - await childVotesERC20 - .connect(childTokenHolder1) - .delegate(childTokenHolder1.address); - await childVotesERC20 - .connect(childTokenHolder2) - .delegate(childTokenHolder2.address); - await parentVotesERC20 - .connect(parentTokenHolder1) - .delegate(parentTokenHolder1.address); - await parentVotesERC20 - .connect(parentTokenHolder2) - .delegate(parentTokenHolder2.address); + await childVotesERC20.connect(childTokenHolder1).delegate(childTokenHolder1.address); + await childVotesERC20.connect(childTokenHolder2).delegate(childTokenHolder2.address); + await parentVotesERC20.connect(parentTokenHolder1).delegate(parentTokenHolder1.address); + await parentVotesERC20.connect(parentTokenHolder2).delegate(parentTokenHolder2.address); // Deploy Azorius module azoriusMastercopy = await new Azorius__factory(deployer).deploy(); const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ mockParentDAO.address, await childGnosisSafe.getAddress(), @@ -227,46 +210,33 @@ describe("Azorius Child DAO with Azorius Parent", () => { [], 60, // Timelock period in blocks 60, // Execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azoriusModule = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azoriusModule = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); // Deploy Linear ERC-20 Voting Strategy - linearERC20VotingMastercopy = await new LinearERC20Voting__factory( - deployer - ).deploy(); + linearERC20VotingMastercopy = await new LinearERC20Voting__factory(deployer).deploy(); const linearERC20VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData("setUp", [ + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - [ - "address", - "address", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], + ['address', 'address', 'address', 'uint32', 'uint256', 'uint256', 'uint256'], [ mockParentDAO.address, // owner await childVotesERC20.getAddress(), // governance token @@ -275,116 +245,104 @@ describe("Azorius Child DAO with Azorius Parent", () => { 0, // proposer weight 500000, // quorom numerator, denominator is 1,000,000 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] + ], ), ]); await moduleProxyFactory.deployModule( await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); const predictedLinearERC20VotingAddress = await calculateProxyAddress( moduleProxyFactory, await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); linearERC20Voting = await hre.ethers.getContractAt( - "LinearERC20Voting", - predictedLinearERC20VotingAddress + 'LinearERC20Voting', + predictedLinearERC20VotingAddress, ); // Enable the Linear Token Voting strategy on Azorius - await azoriusModule - .connect(mockParentDAO) - .enableStrategy(await linearERC20Voting.getAddress()); + await azoriusModule.connect(mockParentDAO).enableStrategy(await linearERC20Voting.getAddress()); // Deploy ERC20FreezeVoting contract - freezeVotingMastercopy = await new ERC20FreezeVoting__factory( - deployer - ).deploy(); + freezeVotingMastercopy = await new ERC20FreezeVoting__factory(deployer).deploy(); const freezeVotingSetupCalldata = // eslint-disable-next-line camelcase - ERC20FreezeVoting__factory.createInterface().encodeFunctionData("setUp", [ + ERC20FreezeVoting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "uint256", "uint32", "uint32", "address"], + ['address', 'uint256', 'uint32', 'uint32', 'address'], [ mockParentDAO.address, // owner 150, // freeze votes threshold 10, // freeze proposal duration in blocks 100, // freeze duration in blocks await parentVotesERC20.getAddress(), - ] + ], ), ]); await moduleProxyFactory.deployModule( await freezeVotingMastercopy.getAddress(), freezeVotingSetupCalldata, - "10031021" + '10031021', ); const predictedFreezeVotingAddress = await calculateProxyAddress( moduleProxyFactory, await freezeVotingMastercopy.getAddress(), freezeVotingSetupCalldata, - "10031021" + '10031021', ); freezeVoting = await hre.ethers.getContractAt( - "ERC20FreezeVoting", - predictedFreezeVotingAddress + 'ERC20FreezeVoting', + predictedFreezeVotingAddress, ); // Deploy and setUp Azorius Freeze Guard contract - freezeGuardMastercopy = await new AzoriusFreezeGuard__factory( - deployer - ).deploy(); + freezeGuardMastercopy = await new AzoriusFreezeGuard__factory(deployer).deploy(); const freezeGuardSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData("setUp", [ + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address"], + ['address', 'address'], [ mockParentDAO.address, // Owner await freezeVoting.getAddress(), // Freeze voting contract - ] + ], ), ]); await moduleProxyFactory.deployModule( await freezeGuardMastercopy.getAddress(), freezeGuardSetupCalldata, - "10031021" + '10031021', ); const predictedFreezeGuardAddress = await calculateProxyAddress( moduleProxyFactory, await freezeGuardMastercopy.getAddress(), freezeGuardSetupCalldata, - "10031021" + '10031021', ); - freezeGuard = await hre.ethers.getContractAt( - "AzoriusFreezeGuard", - predictedFreezeGuardAddress - ); + freezeGuard = await hre.ethers.getContractAt('AzoriusFreezeGuard', predictedFreezeGuardAddress); // Set the Azorius Freeze Guard as the Guard on the Azorius Module - await azoriusModule - .connect(mockParentDAO) - .setGuard(await freezeGuard.getAddress()); + await azoriusModule.connect(mockParentDAO).setGuard(await freezeGuard.getAddress()); // Create transaction on Gnosis Safe to setup Azorius module - const enableAzoriusModuleData = - childGnosisSafe.interface.encodeFunctionData("enableModule", [ - await azoriusModule.getAddress(), - ]); + const enableAzoriusModuleData = childGnosisSafe.interface.encodeFunctionData('enableModule', [ + await azoriusModule.getAddress(), + ]); const enableAzoriusModuleTx = buildSafeTransaction({ to: await childGnosisSafe.getAddress(), @@ -393,13 +351,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { nonce: await childGnosisSafe.nonce(), }); - const sigs = [ - await safeSignTypedData( - childSafeOwner, - childGnosisSafe, - enableAzoriusModuleTx - ), - ]; + const sigs = [await safeSignTypedData(childSafeOwner, childGnosisSafe, enableAzoriusModuleTx)]; const signatureBytes = buildSignatureBytes(sigs); @@ -415,23 +367,21 @@ describe("Azorius Child DAO with Azorius Parent", () => { enableAzoriusModuleTx.gasPrice, enableAzoriusModuleTx.gasToken, enableAzoriusModuleTx.refundReceiver, - signatureBytes - ) - ).to.emit(childGnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(childGnosisSafe, 'ExecutionSuccess'); // Gnosis Safe received the 1,000 tokens - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); }); - describe("FreezeGuard Functionality", () => { - it("A proposal can be created and executed", async () => { + describe('FreezeGuard Functionality', () => { + it('A proposal can be created and executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); const proposalTransaction = { to: await childVotesERC20.getAddress(), @@ -442,9 +392,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - "" + '', ); // Proposal is active @@ -466,9 +416,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Proposal is executable expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -477,34 +425,32 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(0)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("A proposal containing multiple transactions can be created and executed", async () => { + it('A proposal containing multiple transactions can be created and executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 2] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 2, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 3] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 3, + ]); const proposalTransactions = [ { @@ -529,9 +475,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', proposalTransactions, - "" + '', ); // Proposal is active @@ -550,9 +496,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Proposal is executable expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -565,35 +509,33 @@ describe("Azorius Child DAO with Azorius Parent", () => { ], [0, 0, 0], [tokenTransferData1, tokenTransferData2, tokenTransferData3], - [0, 0, 0] + [0, 0, 0], ); // Proposal is executed expect(await azoriusModule.proposalState(0)).to.eq(3); // Check that all three token transfer TX's were executed - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(94); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(94); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(6); }); - it("A frozen DAO cannot execute any transaction", async () => { + it('A frozen DAO cannot execute any transaction', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -618,21 +560,21 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); // Proposal is active @@ -682,9 +624,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -693,9 +635,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -704,18 +646,18 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); }); }); - it("A proposal can still be executed if a freeze proposal has been created, but threshold has not been met", async () => { + it('A proposal can still be executed if a freeze proposal has been created, but threshold has not been met', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); const proposalTransaction = { to: await childVotesERC20.getAddress(), @@ -726,9 +668,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - "" + '', ); // Proposal is active @@ -757,9 +699,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -768,29 +708,27 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(0)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("A frozen DAO is automatically unfrozen after the freeze duration is over", async () => { + it('A frozen DAO is automatically unfrozen after the freeze duration is over', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -808,15 +746,15 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); // Proposal is active @@ -859,9 +797,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -870,19 +808,19 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Increase time so that freeze has ended for (let i = 0; i <= 100; i++) { - await hre.network.provider.send("evm_mine"); + await hre.network.provider.send('evm_mine'); } - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction3 = { to: await childVotesERC20.getAddress(), @@ -893,9 +831,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); expect(await azoriusModule.proposalState(2)).to.eq(0); @@ -915,9 +853,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(2)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -926,34 +862,32 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(2)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(96); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(96); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(4); }); it("A frozen DAO can be unfrozen by its owner, and continue to execute TX's", async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -978,23 +912,23 @@ describe("Azorius Child DAO with Azorius Parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); // Proposal is active @@ -1044,9 +978,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -1055,9 +989,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -1066,9 +1000,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Parent DAO unfreezes the child await freezeVoting.connect(mockParentDAO).unfreeze(); @@ -1076,9 +1010,7 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Child DAO is now unfrozen expect(await freezeVoting.isFrozen()).to.eq(false); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -1087,16 +1019,14 @@ describe("Azorius Child DAO with Azorius Parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] + [0], ); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("Freeze state values are updated correctly throughout the freeze process", async () => { + it('Freeze state values are updated correctly throughout the freeze process', async () => { // freeze votes threshold => 150 // freeze proposal duration in blocks => 10 // freeze duration in blocks => 100 @@ -1104,12 +1034,8 @@ describe("Azorius Child DAO with Azorius Parent", () => { // One voter casts freeze vote await freezeVoting.connect(parentTokenHolder1).castFreezeVote(); - const firstFreezeProposalCreatedBlock = (await hre.ethers.provider.getBlock( - "latest" - ))!.number; - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - firstFreezeProposalCreatedBlock - ); + const firstFreezeProposalCreatedBlock = (await hre.ethers.provider.getBlock('latest'))!.number; + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(firstFreezeProposalCreatedBlock); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(100); @@ -1118,14 +1044,14 @@ describe("Azorius Child DAO with Azorius Parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder1.address, - firstFreezeProposalCreatedBlock - ) + firstFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder2.address, - firstFreezeProposalCreatedBlock - ) + firstFreezeProposalCreatedBlock, + ), ).to.eq(false); // Increase time so freeze proposal has ended @@ -1134,12 +1060,9 @@ describe("Azorius Child DAO with Azorius Parent", () => { // One voter casts freeze vote, this should create a new freeze proposal await freezeVoting.connect(parentTokenHolder1).castFreezeVote(); - const secondFreezeProposalCreatedBlock = - (await hre.ethers.provider.getBlock("latest"))!.number; + const secondFreezeProposalCreatedBlock = (await hre.ethers.provider.getBlock('latest'))!.number; - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock - ); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(secondFreezeProposalCreatedBlock); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(100); @@ -1148,27 +1071,25 @@ describe("Azorius Child DAO with Azorius Parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder1.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder2.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(false); // First voter cannot vote again await expect( - freezeVoting.connect(parentTokenHolder1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "AlreadyVoted"); + freezeVoting.connect(parentTokenHolder1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'AlreadyVoted'); // Second voter casts freeze vote, should update state of current freeze proposal await freezeVoting.connect(parentTokenHolder2).castFreezeVote(); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock - ); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(secondFreezeProposalCreatedBlock); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(200); @@ -1177,14 +1098,14 @@ describe("Azorius Child DAO with Azorius Parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder1.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentTokenHolder2.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); // Move time forward, freeze should still be active @@ -1195,27 +1116,25 @@ describe("Azorius Child DAO with Azorius Parent", () => { // Move time forward, freeze should end await time.advanceBlocks(10); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock - ); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(secondFreezeProposalCreatedBlock); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(200); expect(await freezeVoting.isFrozen()).to.eq(false); }); - it("A user with no freeze votes cannot cast freeze votes", async () => { + it('A user with no freeze votes cannot cast freeze votes', async () => { // User has no freeze votes await expect( - freezeVoting.connect(childTokenHolder1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + freezeVoting.connect(childTokenHolder1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); // Freeze proposal is created await freezeVoting.connect(parentTokenHolder1).castFreezeVote(); // User has no freeze votes await expect( - freezeVoting.connect(childTokenHolder1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + freezeVoting.connect(childTokenHolder1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); }); }); diff --git a/test/AzoriusFreezeGuard-MultisigFreezeVoting.test.ts b/test/AzoriusFreezeGuard-MultisigFreezeVoting.test.ts index ead4aea4..a480bb44 100644 --- a/test/AzoriusFreezeGuard-MultisigFreezeVoting.test.ts +++ b/test/AzoriusFreezeGuard-MultisigFreezeVoting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { GnosisSafeProxyFactory, @@ -19,23 +17,24 @@ import { ModuleProxyFactory, GnosisSafeL2__factory, GnosisSafeL2, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; +} from './helpers'; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +import time from './time'; -describe("Azorius Child DAO with Multisig parent", () => { +describe('Azorius Child DAO with Multisig parent', () => { // Deployed contracts let parentGnosisSafe: GnosisSafeL2; let childGnosisSafe: GnosisSafeL2; @@ -68,9 +67,7 @@ describe("Azorius Child DAO with Multisig parent", () => { let createParentGnosisSetupCalldata: string; const parentThreshold = 2; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); @@ -94,12 +91,8 @@ describe("Azorius Child DAO with Multisig parent", () => { createParentGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [ - parentMultisigOwner1.address, - parentMultisigOwner2.address, - parentMultisigOwner3.address, - ], + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ + [parentMultisigOwner1.address, parentMultisigOwner2.address, parentMultisigOwner3.address], parentThreshold, ethers.ZeroAddress, ethers.ZeroHash, @@ -111,7 +104,7 @@ describe("Azorius Child DAO with Multisig parent", () => { createChildGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [childSafeOwner.address], 1, ethers.ZeroAddress, @@ -126,40 +119,40 @@ describe("Azorius Child DAO with Multisig parent", () => { createParentGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); const predictedChildGnosisSafeAddress = await predictGnosisSafeAddress( createChildGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Parent Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createParentGnosisSetupCalldata, - saltNum + saltNum, ); // Deploy Child Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createChildGnosisSetupCalldata, - saltNum + saltNum, ); // Get Parent Gnosis Safe parentGnosisSafe = await hre.ethers.getContractAt( - "GnosisSafeL2", - predictedParentGnosisSafeAddress + 'GnosisSafeL2', + predictedParentGnosisSafeAddress, ); // Get Child Gnosis Safe childGnosisSafe = await hre.ethers.getContractAt( - "GnosisSafeL2", - predictedChildGnosisSafeAddress + 'GnosisSafeL2', + predictedChildGnosisSafeAddress, ); // Deploy Votes ERC-20 Mastercopy @@ -167,19 +160,19 @@ describe("Azorius Child DAO with Multisig parent", () => { const childVotesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "CHILD", - "CHILD", + 'CHILD', + 'CHILD', [ childTokenHolder1.address, childTokenHolder2.address, await childGnosisSafe.getAddress(), ], [100, 100, 100], - ] + ], ), ]); @@ -188,37 +181,30 @@ describe("Azorius Child DAO with Multisig parent", () => { await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), childVotesERC20SetupData, - "10031021" + '10031021', ); const predictedChildVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), childVotesERC20SetupData, - "10031021" + '10031021', ); - childVotesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedChildVotesERC20Address - ); + childVotesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedChildVotesERC20Address); // Token holders delegate their votes to themselves - await childVotesERC20 - .connect(childTokenHolder1) - .delegate(childTokenHolder1.address); - await childVotesERC20 - .connect(childTokenHolder2) - .delegate(childTokenHolder2.address); + await childVotesERC20.connect(childTokenHolder1).delegate(childTokenHolder1.address); + await childVotesERC20.connect(childTokenHolder2).delegate(childTokenHolder2.address); // Deploy Azorius module mastercopy azoriusMastercopy = await new Azorius__factory(deployer).deploy(); const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ azoriusModuleOwner.address, await childGnosisSafe.getAddress(), @@ -226,46 +212,33 @@ describe("Azorius Child DAO with Multisig parent", () => { [], 60, // Timelock period in blocks 60, // Execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azoriusModule = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azoriusModule = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); // Deploy Linear ERC-20 Voting Strategy Mastercopy - linearERC20VotingMastercopy = await new LinearERC20Voting__factory( - deployer - ).deploy(); + linearERC20VotingMastercopy = await new LinearERC20Voting__factory(deployer).deploy(); const linearERC20VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData("setUp", [ + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - [ - "address", - "address", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], + ['address', 'address', 'address', 'uint32', 'uint256', 'uint256', 'uint256'], [ await parentGnosisSafe.getAddress(), // owner await childVotesERC20.getAddress(), // governance token @@ -274,26 +247,26 @@ describe("Azorius Child DAO with Multisig parent", () => { 0, // proposer weight 500000, // quorom numerator, denominator is 1,000,000 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] + ], ), ]); await moduleProxyFactory.deployModule( await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); const predictedLinearERC20VotingAddress = await calculateProxyAddress( moduleProxyFactory, await linearERC20VotingMastercopy.getAddress(), linearERC20VotingSetupCalldata, - "10031021" + '10031021', ); linearERC20Voting = await hre.ethers.getContractAt( - "LinearERC20Voting", - predictedLinearERC20VotingAddress + 'LinearERC20Voting', + predictedLinearERC20VotingAddress, ); // Enable the Linear Token Voting strategy on Azorius @@ -302,86 +275,75 @@ describe("Azorius Child DAO with Multisig parent", () => { .enableStrategy(await linearERC20Voting.getAddress()); // Deploy MultisigFreezeVoting mastercopy contract - freezeVotingMastercopy = await new MultisigFreezeVoting__factory( - deployer - ).deploy(); + freezeVotingMastercopy = await new MultisigFreezeVoting__factory(deployer).deploy(); const freezeVotingSetupCalldata = // eslint-disable-next-line camelcase - MultisigFreezeVoting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["address", "uint256", "uint32", "uint32", "address"], - [ - freezeVotingOwner.address, // owner - 2, // freeze votes threshold - 10, // freeze proposal duration in blocks - 200, // freeze duration in blocks - await parentGnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeVoting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['address', 'uint256', 'uint32', 'uint32', 'address'], + [ + freezeVotingOwner.address, // owner + 2, // freeze votes threshold + 10, // freeze proposal duration in blocks + 200, // freeze duration in blocks + await parentGnosisSafe.getAddress(), + ], + ), + ]); await moduleProxyFactory.deployModule( await freezeVotingMastercopy.getAddress(), freezeVotingSetupCalldata, - "10031021" + '10031021', ); const predictedFreezeVotingAddress = await calculateProxyAddress( moduleProxyFactory, await freezeVotingMastercopy.getAddress(), freezeVotingSetupCalldata, - "10031021" + '10031021', ); freezeVoting = await hre.ethers.getContractAt( - "MultisigFreezeVoting", - predictedFreezeVotingAddress + 'MultisigFreezeVoting', + predictedFreezeVotingAddress, ); // Deploy and setUp AzoriusFreezeGuard mastercopy contract - freezeGuardMastercopy = await new AzoriusFreezeGuard__factory( - deployer - ).deploy(); + freezeGuardMastercopy = await new AzoriusFreezeGuard__factory(deployer).deploy(); const freezeGuardSetupCalldata = // eslint-disable-next-line camelcase - LinearERC20Voting__factory.createInterface().encodeFunctionData("setUp", [ + LinearERC20Voting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address"], + ['address', 'address'], [ freezeVotingOwner.address, // owner await freezeVoting.getAddress(), // freeze voting contract - ] + ], ), ]); await moduleProxyFactory.deployModule( await freezeGuardMastercopy.getAddress(), freezeGuardSetupCalldata, - "10031021" + '10031021', ); const predictedFreezeGuardAddress = await calculateProxyAddress( moduleProxyFactory, await freezeGuardMastercopy.getAddress(), freezeGuardSetupCalldata, - "10031021" + '10031021', ); - freezeGuard = await hre.ethers.getContractAt( - "AzoriusFreezeGuard", - predictedFreezeGuardAddress - ); + freezeGuard = await hre.ethers.getContractAt('AzoriusFreezeGuard', predictedFreezeGuardAddress); // Create transaction on child Gnosis Safe to setup Azorius module - const enableAzoriusModuleData = - childGnosisSafe.interface.encodeFunctionData("enableModule", [ - await azoriusModule.getAddress(), - ]); + const enableAzoriusModuleData = childGnosisSafe.interface.encodeFunctionData('enableModule', [ + await azoriusModule.getAddress(), + ]); const enableAzoriusModuleTx = buildSafeTransaction({ to: await childGnosisSafe.getAddress(), @@ -390,13 +352,7 @@ describe("Azorius Child DAO with Multisig parent", () => { nonce: await childGnosisSafe.nonce(), }); - const sigs = [ - await safeSignTypedData( - childSafeOwner, - childGnosisSafe, - enableAzoriusModuleTx - ), - ]; + const sigs = [await safeSignTypedData(childSafeOwner, childGnosisSafe, enableAzoriusModuleTx)]; const signatureBytes = buildSignatureBytes(sigs); @@ -412,28 +368,24 @@ describe("Azorius Child DAO with Multisig parent", () => { enableAzoriusModuleTx.gasPrice, enableAzoriusModuleTx.gasToken, enableAzoriusModuleTx.refundReceiver, - signatureBytes - ) - ).to.emit(childGnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(childGnosisSafe, 'ExecutionSuccess'); // Set the Azorius Freeze Guard as the Guard on the Azorius Module - await azoriusModule - .connect(azoriusModuleOwner) - .setGuard(await freezeGuard.getAddress()); + await azoriusModule.connect(azoriusModuleOwner).setGuard(await freezeGuard.getAddress()); // Gnosis Safe received the 100 tokens - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); }); - describe("AzoriusFreezeGuard Functionality", () => { - it("A proposal can be created and executed", async () => { + describe('AzoriusFreezeGuard Functionality', () => { + it('A proposal can be created and executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); const proposalTransaction = { to: await childVotesERC20.getAddress(), @@ -444,9 +396,9 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - "" + '', ); // Proposal is active @@ -468,9 +420,7 @@ describe("Azorius Child DAO with Multisig parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -479,31 +429,29 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData], - [0] + [0], ); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("A proposal containing multiple transactions can be created and executed", async () => { + it('A proposal containing multiple transactions can be created and executed', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 2] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 2, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 3] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 3, + ]); const proposalTransactions = [ { @@ -528,9 +476,9 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', proposalTransactions, - "" + '', ); // Proposal is active @@ -552,9 +500,7 @@ describe("Azorius Child DAO with Multisig parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -567,32 +513,30 @@ describe("Azorius Child DAO with Multisig parent", () => { ], [0, 0, 0], [tokenTransferData1, tokenTransferData2, tokenTransferData3], - [0, 0, 0] + [0, 0, 0], ); // Check that all three token transfer TX's were executed - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(94); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(94); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(6); }); - it("A frozen DAO cannot execute any transaction", async () => { + it('A frozen DAO cannot execute any transaction', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -617,21 +561,21 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); // Proposal is active @@ -681,9 +625,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -692,9 +636,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -703,17 +647,17 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); }); - it("A proposal can still be executed if a freeze proposal has been created, but threshold has not been met", async () => { + it('A proposal can still be executed if a freeze proposal has been created, but threshold has not been met', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); const proposalTransaction = { to: await childVotesERC20.getAddress(), @@ -724,9 +668,9 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction], - "" + '', ); // Proposal is active @@ -755,9 +699,7 @@ describe("Azorius Child DAO with Multisig parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(0)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -766,29 +708,27 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(0)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("A frozen DAO is automatically unfrozen after the freeze duration is over", async () => { + it('A frozen DAO is automatically unfrozen after the freeze duration is over', async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -806,16 +746,16 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); // Proposal is active @@ -858,9 +798,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -869,17 +809,17 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Increase time so that freeze period has ended await time.advanceBlocks(200); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction3 = { to: await childVotesERC20.getAddress(), @@ -890,9 +830,9 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); expect(await azoriusModule.proposalState(2)).to.eq(0); @@ -912,9 +852,7 @@ describe("Azorius Child DAO with Multisig parent", () => { // Proposal is ready to execute expect(await azoriusModule.proposalState(2)).to.eq(2); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -923,34 +861,32 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(2)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(96); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(96); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(4); }); it("A frozen DAO can be unfrozen by its owner, and continue to execute TX's", async () => { // Create transaction to transfer tokens to the deployer - const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 10] - ); + const tokenTransferData1 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 10, + ]); - const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 5] - ); + const tokenTransferData2 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 5, + ]); - const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 4] - ); + const tokenTransferData3 = childVotesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 4, + ]); const proposalTransaction1 = { to: await childVotesERC20.getAddress(), @@ -975,21 +911,21 @@ describe("Azorius Child DAO with Multisig parent", () => { await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction1], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction2], - "" + '', ); await azoriusModule.submitProposal( await linearERC20Voting.getAddress(), - "0x", + '0x', [proposalTransaction3], - "" + '', ); // Proposal is active @@ -1039,9 +975,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -1050,9 +986,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData2], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // This proposal should fail due to freeze await expect( @@ -1061,9 +997,9 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData3], - [0] - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + [0], + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Parent DAO unfreezes the child await freezeVoting.connect(freezeVotingOwner).unfreeze(); @@ -1071,9 +1007,7 @@ describe("Azorius Child DAO with Multisig parent", () => { // Child DAO is now unfrozen expect(await freezeVoting.isFrozen()).to.eq(false); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(100); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(100); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(0); // Execute the transaction @@ -1082,19 +1016,17 @@ describe("Azorius Child DAO with Multisig parent", () => { [await childVotesERC20.getAddress()], [0], [tokenTransferData1], - [0] + [0], ); // Proposal is executed expect(await azoriusModule.proposalState(0)).to.eq(3); - expect( - await childVotesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(90); + expect(await childVotesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(90); expect(await childVotesERC20.balanceOf(deployer.address)).to.eq(10); }); - it("Freeze state values are updated correctly throughout the freeze process", async () => { + it('Freeze state values are updated correctly throughout the freeze process', async () => { // freeze votes threshold => 2 // freeze proposal duration in blocks => 10 // freeze duration in blocks => 200 @@ -1102,10 +1034,10 @@ describe("Azorius Child DAO with Multisig parent", () => { // One voter casts freeze vote await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); - const firstFreezeProposalCreatedBlock = - (await hre.ethers.provider.getBlock("latest"))!.number; + const firstFreezeProposalCreatedBlock = (await hre.ethers.provider.getBlock('latest'))! + .number; expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - firstFreezeProposalCreatedBlock + firstFreezeProposalCreatedBlock, ); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); @@ -1115,14 +1047,14 @@ describe("Azorius Child DAO with Multisig parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner1.address, - firstFreezeProposalCreatedBlock - ) + firstFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner2.address, - firstFreezeProposalCreatedBlock - ) + firstFreezeProposalCreatedBlock, + ), ).to.eq(false); // Increase time so freeze proposal has ended @@ -1131,11 +1063,11 @@ describe("Azorius Child DAO with Multisig parent", () => { // One voter casts freeze vote, this should create a new freeze proposal await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); - const secondFreezeProposalCreatedBlock = - (await hre.ethers.provider.getBlock("latest"))!.number; + const secondFreezeProposalCreatedBlock = (await hre.ethers.provider.getBlock('latest'))! + .number; expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock + secondFreezeProposalCreatedBlock, ); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); @@ -1145,26 +1077,26 @@ describe("Azorius Child DAO with Multisig parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner1.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner2.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(false); // First voter cannot vote again await expect( - freezeVoting.connect(parentMultisigOwner1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "AlreadyVoted"); + freezeVoting.connect(parentMultisigOwner1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'AlreadyVoted'); // Second voter casts freeze vote, should update state of current freeze proposal await freezeVoting.connect(parentMultisigOwner2).castFreezeVote(); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock + secondFreezeProposalCreatedBlock, ); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(2); @@ -1174,14 +1106,14 @@ describe("Azorius Child DAO with Multisig parent", () => { expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner1.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); expect( await freezeVoting.userHasFreezeVoted( parentMultisigOwner2.address, - secondFreezeProposalCreatedBlock - ) + secondFreezeProposalCreatedBlock, + ), ).to.eq(true); // Move time forward, freeze should still be active @@ -1193,7 +1125,7 @@ describe("Azorius Child DAO with Multisig parent", () => { await time.advanceBlocks(200); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - secondFreezeProposalCreatedBlock + secondFreezeProposalCreatedBlock, ); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(2); diff --git a/test/DecentHats_0_1_0.test.ts b/test/DecentHats_0_1_0.test.ts index 6c308a50..d20a600c 100644 --- a/test/DecentHats_0_1_0.test.ts +++ b/test/DecentHats_0_1_0.test.ts @@ -1,3 +1,6 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { GnosisSafeL2, GnosisSafeL2__factory, @@ -15,24 +18,12 @@ import { MockSablierV2LockupLinear, MockERC20__factory, MockERC20, -} from "../typechain-types"; +} from '../typechain-types'; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; +import { getGnosisSafeL2Singleton, getGnosisSafeProxyFactory } from './GlobalSafeDeployments.test'; +import { executeSafeTransaction, getHatAccount, predictGnosisSafeAddress } from './helpers'; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, -} from "./GlobalSafeDeployments.test"; -import { - executeSafeTransaction, - getHatAccount, - predictGnosisSafeAddress, -} from "./helpers"; - -describe("DecentHats_0_1_0", () => { +describe('DecentHats_0_1_0', () => { let dao: SignerWithAddress; let mockHats: MockHats; @@ -65,21 +56,18 @@ describe("DecentHats_0_1_0", () => { mockHatsAddress = await mockHats.getAddress(); keyValuePairs = await new KeyValuePairs__factory(deployer).deploy(); erc6551Registry = await new ERC6551Registry__factory(deployer).deploy(); - mockHatsAccountImplementation = await new MockHatsAccount__factory( - deployer - ).deploy(); - mockHatsAccountImplementationAddress = - await mockHatsAccountImplementation.getAddress(); + mockHatsAccountImplementation = await new MockHatsAccount__factory(deployer).deploy(); + mockHatsAccountImplementationAddress = await mockHatsAccountImplementation.getAddress(); decentHats = await new DecentHats_0_1_0__factory(deployer).deploy(); decentHatsAddress = await decentHats.getAddress(); const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); const gnosisSafeL2Singleton = getGnosisSafeL2Singleton(); - const gnosisSafeL2SingletonAddress = - await gnosisSafeL2Singleton.getAddress(); + const gnosisSafeL2SingletonAddress = await gnosisSafeL2Singleton.getAddress(); - const createGnosisSetupCalldata = - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + const createGnosisSetupCalldata = GnosisSafeL2__factory.createInterface().encodeFunctionData( + 'setup', + [ [dao.address], 1, hre.ethers.ZeroAddress, @@ -88,202 +76,182 @@ describe("DecentHats_0_1_0", () => { hre.ethers.ZeroAddress, 0, hre.ethers.ZeroAddress, - ]); - - const saltNum = BigInt( - `0x${Buffer.from(hre.ethers.randomBytes(32)).toString("hex")}` + ], ); + const saltNum = BigInt(`0x${Buffer.from(hre.ethers.randomBytes(32)).toString('hex')}`); + const predictedGnosisSafeAddress = await predictGnosisSafeAddress( createGnosisSetupCalldata, saltNum, gnosisSafeL2SingletonAddress, - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); gnosisSafeAddress = predictedGnosisSafeAddress; await gnosisSafeProxyFactory.createProxyWithNonce( gnosisSafeL2SingletonAddress, createGnosisSetupCalldata, - saltNum + saltNum, ); - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); // Deploy MockSablierV2LockupLinear - mockSablier = await new MockSablierV2LockupLinear__factory( - deployer - ).deploy(); + mockSablier = await new MockSablierV2LockupLinear__factory(deployer).deploy(); mockSablierAddress = await mockSablier.getAddress(); - mockERC20 = await new MockERC20__factory(deployer).deploy( - "MockERC20", - "MCK" - ); + mockERC20 = await new MockERC20__factory(deployer).deploy('MockERC20', 'MCK'); mockERC20Address = await mockERC20.getAddress(); - await mockERC20.mint(gnosisSafeAddress, ethers.parseEther("1000000")); + await mockERC20.mint(gnosisSafeAddress, ethers.parseEther('1000000')); }); - describe("DecentHats", () => { + describe('DecentHats', () => { let enableModuleTx: ethers.ContractTransactionResponse; beforeEach(async () => { enableModuleTx = await executeSafeTransaction({ safe: gnosisSafe, to: gnosisSafeAddress, - transactionData: - GnosisSafeL2__factory.createInterface().encodeFunctionData( - "enableModule", - [decentHatsAddress] - ), + transactionData: GnosisSafeL2__factory.createInterface().encodeFunctionData( + 'enableModule', + [decentHatsAddress], + ), signers: [dao], }); }); - describe("Enabled as a module", () => { - it("Emits an ExecutionSuccess event", async () => { - await expect(enableModuleTx).to.emit(gnosisSafe, "ExecutionSuccess"); + describe('Enabled as a module', () => { + it('Emits an ExecutionSuccess event', async () => { + await expect(enableModuleTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an EnabledModule event", async () => { + it('Emits an EnabledModule event', async () => { await expect(enableModuleTx) - .to.emit(gnosisSafe, "EnabledModule") + .to.emit(gnosisSafe, 'EnabledModule') .withArgs(decentHatsAddress); }); }); - describe("Creating a new Top Hat and Tree", () => { + describe('Creating a new Top Hat and Tree', () => { let createAndDeclareTreeTx: ethers.ContractTransactionResponse; beforeEach(async () => { createAndDeclareTreeTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: await erc6551Registry.getAddress(), - keyValuePairs: await keyValuePairs.getAddress(), - topHatDetails: "", - topHatImageURI: "", - adminHat: { + transactionData: DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + 'createAndDeclareTree', + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: '', + topHatImageURI: '', + adminHat: { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { maxSupply: 1, - details: "", - imageURI: "", + details: '', + imageURI: '', isMutable: false, wearer: ethers.ZeroAddress, sablierParams: [], }, - hats: [ - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [], - }, - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [], - }, - ], - }, - ] - ), + { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + ], + }, + ], + ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(createAndDeclareTreeTx).to.emit( - gnosisSafe, - "ExecutionSuccess" - ); + it('Emits an ExecutionSuccess event', async () => { + await expect(createAndDeclareTreeTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an ExecutionFromModuleSuccess event", async () => { + it('Emits an ExecutionFromModuleSuccess event', async () => { await expect(createAndDeclareTreeTx) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .to.emit(gnosisSafe, 'ExecutionFromModuleSuccess') .withArgs(decentHatsAddress); }); - it("Emits some hatsTreeId ValueUpdated events", async () => { + it('Emits some hatsTreeId ValueUpdated events', async () => { await expect(createAndDeclareTreeTx) - .to.emit(keyValuePairs, "ValueUpdated") - .withArgs(gnosisSafeAddress, "topHatId", "0"); + .to.emit(keyValuePairs, 'ValueUpdated') + .withArgs(gnosisSafeAddress, 'topHatId', '0'); }); - describe("Multiple calls", () => { + describe('Multiple calls', () => { let createAndDeclareTreeTx2: ethers.ContractTransactionResponse; beforeEach(async () => { createAndDeclareTreeTx2 = await executeSafeTransaction({ safe: gnosisSafe, to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: await erc6551Registry.getAddress(), - keyValuePairs: await keyValuePairs.getAddress(), - topHatDetails: "", - topHatImageURI: "", - adminHat: { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [], - }, - hats: [], + transactionData: DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + 'createAndDeclareTree', + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: '', + topHatImageURI: '', + adminHat: { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], }, - ] - ), + hats: [], + }, + ], + ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(createAndDeclareTreeTx2).to.emit( - gnosisSafe, - "ExecutionSuccess" - ); + it('Emits an ExecutionSuccess event', async () => { + await expect(createAndDeclareTreeTx2).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an ExecutionFromModuleSuccess event", async () => { + it('Emits an ExecutionFromModuleSuccess event', async () => { await expect(createAndDeclareTreeTx2) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .to.emit(gnosisSafe, 'ExecutionFromModuleSuccess') .withArgs(decentHatsAddress); }); - it("Creates Top Hats with sequential IDs", async () => { + it('Creates Top Hats with sequential IDs', async () => { await expect(createAndDeclareTreeTx2) - .to.emit(keyValuePairs, "ValueUpdated") - .withArgs(gnosisSafeAddress, "topHatId", "4"); + .to.emit(keyValuePairs, 'ValueUpdated') + .withArgs(gnosisSafeAddress, 'topHatId', '4'); }); }); - describe("Creating Hats Accounts", () => { - it("Generates the correct Addresses for the current Hats", async () => { + describe('Creating Hats Accounts', () => { + it('Generates the correct Addresses for the current Hats', async () => { const currentCount = await mockHats.count(); for (let i = 0n; i < currentCount; i++) { @@ -291,130 +259,122 @@ describe("DecentHats_0_1_0", () => { i, erc6551Registry, mockHatsAccountImplementationAddress, - mockHatsAddress + mockHatsAddress, ); expect(await topHatAccount.tokenId()).eq(i); - expect(await topHatAccount.tokenImplementation()).eq( - mockHatsAddress - ); + expect(await topHatAccount.tokenImplementation()).eq(mockHatsAddress); } }); }); }); - describe("Creating a new Top Hat and Tree with Sablier Streams", () => { + describe('Creating a new Top Hat and Tree with Sablier Streams', () => { let createAndDeclareTreeTx: ethers.ContractTransactionResponse; let currentBlockTimestamp: number; beforeEach(async () => { - currentBlockTimestamp = (await hre.ethers.provider.getBlock("latest"))! - .timestamp; + currentBlockTimestamp = (await hre.ethers.provider.getBlock('latest'))!.timestamp; createAndDeclareTreeTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: await erc6551Registry.getAddress(), - keyValuePairs: await keyValuePairs.getAddress(), - topHatDetails: "", - topHatImageURI: "", - adminHat: { + transactionData: DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + 'createAndDeclareTree', + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: '', + topHatImageURI: '', + adminHat: { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { maxSupply: 1, - details: "", - imageURI: "", + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [ + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther('100'), + asset: mockERC20Address, + cancelable: true, + transferable: false, + timestamps: { + start: currentBlockTimestamp, + cliff: 0, + end: currentBlockTimestamp + 2592000, // 30 days from now + }, + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + ], + }, + { + maxSupply: 1, + details: '', + imageURI: '', isMutable: false, wearer: ethers.ZeroAddress, sablierParams: [], }, - hats: [ - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [ - { - sablier: mockSablierAddress, - sender: gnosisSafeAddress, - totalAmount: ethers.parseEther("100"), - asset: mockERC20Address, - cancelable: true, - transferable: false, - timestamps: { - start: currentBlockTimestamp, - cliff: 0, - end: currentBlockTimestamp + 2592000, // 30 days from now - }, - broker: { account: ethers.ZeroAddress, fee: 0 }, - }, - ], - }, - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [], - }, - ], - }, - ] - ), + ], + }, + ], + ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(createAndDeclareTreeTx).to.emit( - gnosisSafe, - "ExecutionSuccess" - ); + it('Emits an ExecutionSuccess event', async () => { + await expect(createAndDeclareTreeTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an ExecutionFromModuleSuccess event", async () => { + it('Emits an ExecutionFromModuleSuccess event', async () => { await expect(createAndDeclareTreeTx) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .to.emit(gnosisSafe, 'ExecutionFromModuleSuccess') .withArgs(decentHatsAddress); }); - it("Emits some hatsTreeId ValueUpdated events", async () => { + it('Emits some hatsTreeId ValueUpdated events', async () => { await expect(createAndDeclareTreeTx) - .to.emit(keyValuePairs, "ValueUpdated") - .withArgs(gnosisSafeAddress, "topHatId", "0"); + .to.emit(keyValuePairs, 'ValueUpdated') + .withArgs(gnosisSafeAddress, 'topHatId', '0'); }); - it("Creates a Sablier stream for the hat with stream parameters", async () => { + it('Creates a Sablier stream for the hat with stream parameters', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); expect(streamCreatedEvents.length).to.equal(1); const event = streamCreatedEvents[0]; expect(event.args.sender).to.equal(gnosisSafeAddress); expect(event.args.recipient).to.not.equal(ethers.ZeroAddress); - expect(event.args.totalAmount).to.equal(ethers.parseEther("100")); + expect(event.args.totalAmount).to.equal(ethers.parseEther('100')); }); - it("Does not create a Sablier stream for hats without stream parameters", async () => { + it('Does not create a Sablier stream for hats without stream parameters', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); expect(streamCreatedEvents.length).to.equal(1); // Only one stream should be created }); - it("Creates a Sablier stream with correct timestamps", async () => { + it('Creates a Sablier stream with correct timestamps', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); expect(streamCreatedEvents.length).to.equal(1); @@ -426,133 +386,122 @@ describe("DecentHats_0_1_0", () => { }); }); - describe("Creating a new Top Hat and Tree with Multiple Sablier Streams per Hat", () => { + describe('Creating a new Top Hat and Tree with Multiple Sablier Streams per Hat', () => { let currentBlockTimestamp: number; beforeEach(async () => { - currentBlockTimestamp = (await hre.ethers.provider.getBlock("latest"))! - .timestamp; + currentBlockTimestamp = (await hre.ethers.provider.getBlock('latest'))!.timestamp; await executeSafeTransaction({ safe: gnosisSafe, to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: await erc6551Registry.getAddress(), - keyValuePairs: await keyValuePairs.getAddress(), - topHatDetails: "", - topHatImageURI: "", - adminHat: { + transactionData: DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + 'createAndDeclareTree', + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: '', + topHatImageURI: '', + adminHat: { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { maxSupply: 1, - details: "", - imageURI: "", + details: '', + imageURI: '', isMutable: false, wearer: ethers.ZeroAddress, - sablierParams: [], - }, - hats: [ - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [ - { - sablier: mockSablierAddress, - sender: gnosisSafeAddress, - totalAmount: ethers.parseEther("100"), - asset: mockERC20Address, - cancelable: true, - transferable: false, - timestamps: { - start: currentBlockTimestamp, - cliff: currentBlockTimestamp + 86400, // 1 day cliff - end: currentBlockTimestamp + 2592000, // 30 days from now - }, - broker: { account: ethers.ZeroAddress, fee: 0 }, + sablierParams: [ + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther('100'), + asset: mockERC20Address, + cancelable: true, + transferable: false, + timestamps: { + start: currentBlockTimestamp, + cliff: currentBlockTimestamp + 86400, // 1 day cliff + end: currentBlockTimestamp + 2592000, // 30 days from now }, - { - sablier: mockSablierAddress, - sender: gnosisSafeAddress, - totalAmount: ethers.parseEther("50"), - asset: mockERC20Address, - cancelable: false, - transferable: true, - timestamps: { - start: currentBlockTimestamp, - cliff: 0, // No cliff - end: currentBlockTimestamp + 1296000, // 15 days from now - }, - broker: { account: ethers.ZeroAddress, fee: 0 }, + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther('50'), + asset: mockERC20Address, + cancelable: false, + transferable: true, + timestamps: { + start: currentBlockTimestamp, + cliff: 0, // No cliff + end: currentBlockTimestamp + 1296000, // 15 days from now }, - ], - }, - ], - }, - ] - ), + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + ], + }, + ], + }, + ], + ), signers: [dao], }); }); - it("Creates multiple Sablier streams for a single hat", async () => { + it('Creates multiple Sablier streams for a single hat', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); expect(streamCreatedEvents.length).to.equal(2); const event1 = streamCreatedEvents[0]; expect(event1.args.sender).to.equal(gnosisSafeAddress); expect(event1.args.recipient).to.not.equal(ethers.ZeroAddress); - expect(event1.args.totalAmount).to.equal(ethers.parseEther("100")); + expect(event1.args.totalAmount).to.equal(ethers.parseEther('100')); const event2 = streamCreatedEvents[1]; expect(event2.args.sender).to.equal(gnosisSafeAddress); expect(event2.args.recipient).to.equal(event1.args.recipient); - expect(event2.args.totalAmount).to.equal(ethers.parseEther("50")); + expect(event2.args.totalAmount).to.equal(ethers.parseEther('50')); }); - it("Creates streams with correct parameters", async () => { + it('Creates streams with correct parameters', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); - const stream1 = await mockSablier.getStream( - streamCreatedEvents[0].args.streamId - ); - expect(stream1.cancelable).to.be.true; - expect(stream1.transferable).to.be.false; + const stream1 = await mockSablier.getStream(streamCreatedEvents[0].args.streamId); + expect(stream1.cancelable === true); + expect(stream1.transferable === false); expect(stream1.endTime - stream1.startTime).to.equal(2592000); - const stream2 = await mockSablier.getStream( - streamCreatedEvents[1].args.streamId - ); - expect(stream2.cancelable).to.be.false; - expect(stream2.transferable).to.be.true; + const stream2 = await mockSablier.getStream(streamCreatedEvents[1].args.streamId); + expect(stream2.cancelable === false); + expect(stream2.transferable === true); expect(stream2.endTime - stream2.startTime).to.equal(1296000); }); - it("Creates streams with correct timestamps", async () => { + it('Creates streams with correct timestamps', async () => { const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() + mockSablier.filters.StreamCreated(), ); - const stream1 = await mockSablier.getStream( - streamCreatedEvents[0].args.streamId - ); + const stream1 = await mockSablier.getStream(streamCreatedEvents[0].args.streamId); expect(stream1.startTime).to.equal(currentBlockTimestamp); expect(stream1.endTime).to.equal(currentBlockTimestamp + 2592000); - const stream2 = await mockSablier.getStream( - streamCreatedEvents[1].args.streamId - ); + const stream2 = await mockSablier.getStream(streamCreatedEvents[1].args.streamId); expect(stream2.startTime).to.equal(currentBlockTimestamp); expect(stream2.endTime).to.equal(currentBlockTimestamp + 1296000); }); diff --git a/test/DecentSablierStreamManagement.test.ts b/test/DecentSablierStreamManagement.test.ts index 227477c4..de11ac61 100644 --- a/test/DecentSablierStreamManagement.test.ts +++ b/test/DecentSablierStreamManagement.test.ts @@ -1,3 +1,6 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { DecentHats_0_1_0, DecentHats_0_1_0__factory, @@ -16,25 +19,12 @@ import { MockHatsAccount__factory, MockSablierV2LockupLinear, MockSablierV2LockupLinear__factory, -} from "../typechain-types"; +} from '../typechain-types'; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; +import { getGnosisSafeProxyFactory, getGnosisSafeL2Singleton } from './GlobalSafeDeployments.test'; +import { executeSafeTransaction, getHatAccount, predictGnosisSafeAddress } from './helpers'; -import { - executeSafeTransaction, - getHatAccount, - predictGnosisSafeAddress, -} from "./helpers"; - -import { - getGnosisSafeProxyFactory, - getGnosisSafeL2Singleton, -} from "./GlobalSafeDeployments.test"; - -describe("DecentSablierStreamManagement", () => { +describe('DecentSablierStreamManagement', () => { let dao: SignerWithAddress; let gnosisSafe: GnosisSafeL2; @@ -66,34 +56,29 @@ describe("DecentSablierStreamManagement", () => { let enableModuleTx: ethers.ContractTransactionResponse; let createAndDeclareTreeWithRolesAndStreamsTx: ethers.ContractTransactionResponse; - const streamFundsMax = ethers.parseEther("100"); + const streamFundsMax = ethers.parseEther('100'); beforeEach(async () => { const signers = await hre.ethers.getSigners(); const [deployer] = signers; [, dao] = signers; - decentSablierManagement = await new DecentSablierStreamManagement__factory( - deployer - ).deploy(); + decentSablierManagement = await new DecentSablierStreamManagement__factory(deployer).deploy(); decentSablierManagementAddress = await decentSablierManagement.getAddress(); - mockHatsAccountImplementation = await new MockHatsAccount__factory( - deployer - ).deploy(); - mockHatsAccountImplementationAddress = - await mockHatsAccountImplementation.getAddress(); + mockHatsAccountImplementation = await new MockHatsAccount__factory(deployer).deploy(); + mockHatsAccountImplementationAddress = await mockHatsAccountImplementation.getAddress(); decentHats = await new DecentHats_0_1_0__factory(deployer).deploy(); decentHatsAddress = await decentHats.getAddress(); const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); const gnosisSafeL2Singleton = getGnosisSafeL2Singleton(); - const gnosisSafeL2SingletonAddress = - await gnosisSafeL2Singleton.getAddress(); + const gnosisSafeL2SingletonAddress = await gnosisSafeL2Singleton.getAddress(); - const createGnosisSetupCalldata = - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + const createGnosisSetupCalldata = GnosisSafeL2__factory.createInterface().encodeFunctionData( + 'setup', + [ [dao.address], 1, hre.ethers.ZeroAddress, @@ -102,59 +87,47 @@ describe("DecentSablierStreamManagement", () => { hre.ethers.ZeroAddress, 0, hre.ethers.ZeroAddress, - ]); - - const saltNum = BigInt( - `0x${Buffer.from(hre.ethers.randomBytes(32)).toString("hex")}` + ], ); + const saltNum = BigInt(`0x${Buffer.from(hre.ethers.randomBytes(32)).toString('hex')}`); + const predictedGnosisSafeAddress = await predictGnosisSafeAddress( createGnosisSetupCalldata, saltNum, gnosisSafeL2SingletonAddress, - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); gnosisSafeAddress = predictedGnosisSafeAddress; await gnosisSafeProxyFactory.createProxyWithNonce( gnosisSafeL2SingletonAddress, createGnosisSetupCalldata, - saltNum + saltNum, ); - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); // Deploy MockSablierV2LockupLinear - mockSablier = await new MockSablierV2LockupLinear__factory( - deployer - ).deploy(); + mockSablier = await new MockSablierV2LockupLinear__factory(deployer).deploy(); mockSablierAddress = await mockSablier.getAddress(); - mockERC20 = await new MockERC20__factory(deployer).deploy( - "MockERC20", - "MCK" - ); + mockERC20 = await new MockERC20__factory(deployer).deploy('MockERC20', 'MCK'); mockERC20Address = await mockERC20.getAddress(); - await mockERC20.mint(gnosisSafeAddress, ethers.parseEther("1000000")); + await mockERC20.mint(gnosisSafeAddress, ethers.parseEther('1000000')); // Set up the Safe with roles and streams await executeSafeTransaction({ safe: gnosisSafe, to: gnosisSafeAddress, - transactionData: - GnosisSafeL2__factory.createInterface().encodeFunctionData( - "enableModule", - [decentHatsAddress] - ), + transactionData: GnosisSafeL2__factory.createInterface().encodeFunctionData('enableModule', [ + decentHatsAddress, + ]), signers: [dao], }); - currentBlockTimestamp = (await hre.ethers.provider.getBlock("latest"))! - .timestamp; + currentBlockTimestamp = (await hre.ethers.provider.getBlock('latest'))!.timestamp; mockHats = await new MockHats__factory(deployer).deploy(); mockHatsAddress = await mockHats.getAddress(); @@ -164,68 +137,62 @@ describe("DecentSablierStreamManagement", () => { createAndDeclareTreeWithRolesAndStreamsTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: mockHatsAccountImplementationAddress, - registry: await erc6551Registry.getAddress(), - keyValuePairs: await keyValuePairs.getAddress(), - topHatDetails: "", - topHatImageURI: "", - adminHat: { + transactionData: DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + 'createAndDeclareTree', + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: '', + topHatImageURI: '', + adminHat: { + maxSupply: 1, + details: '', + imageURI: '', + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { maxSupply: 1, - details: "", - imageURI: "", + details: '', + imageURI: '', isMutable: false, - wearer: ethers.ZeroAddress, - sablierParams: [], - }, - hats: [ - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: dao.address, - sablierParams: [ - { - sablier: mockSablierAddress, - sender: gnosisSafeAddress, - totalAmount: streamFundsMax, - asset: mockERC20Address, - cancelable: true, - transferable: false, - timestamps: { - start: currentBlockTimestamp, - cliff: 0, - end: currentBlockTimestamp + 2592000, // 30 days from now - }, - broker: { account: ethers.ZeroAddress, fee: 0 }, + wearer: dao.address, + sablierParams: [ + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: streamFundsMax, + asset: mockERC20Address, + cancelable: true, + transferable: false, + timestamps: { + start: currentBlockTimestamp, + cliff: 0, + end: currentBlockTimestamp + 2592000, // 30 days from now }, - ], - }, - ], - }, - ] - ), + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + ], + }, + ], + }, + ], + ), signers: [dao], }); + await expect(createAndDeclareTreeWithRolesAndStreamsTx).to.emit(gnosisSafe, 'ExecutionSuccess'); await expect(createAndDeclareTreeWithRolesAndStreamsTx).to.emit( gnosisSafe, - "ExecutionSuccess" - ); - await expect(createAndDeclareTreeWithRolesAndStreamsTx).to.emit( - gnosisSafe, - "ExecutionFromModuleSuccess" + 'ExecutionFromModuleSuccess', ); - const streamCreatedEvents = await mockSablier.queryFilter( - mockSablier.filters.StreamCreated() - ); + const streamCreatedEvents = await mockSablier.queryFilter(mockSablier.filters.StreamCreated()); expect(streamCreatedEvents.length).to.equal(1); streamId = streamCreatedEvents[0].args.streamId; @@ -234,49 +201,45 @@ describe("DecentSablierStreamManagement", () => { enableModuleTx = await executeSafeTransaction({ safe: gnosisSafe, to: gnosisSafeAddress, - transactionData: - GnosisSafeL2__factory.createInterface().encodeFunctionData( - "enableModule", - [decentSablierManagementAddress] - ), + transactionData: GnosisSafeL2__factory.createInterface().encodeFunctionData('enableModule', [ + decentSablierManagementAddress, + ]), signers: [dao], }); }); - describe("Enabled as a Module", () => { - it("Emits an ExecutionSuccess event", async () => { - await expect(enableModuleTx).to.emit(gnosisSafe, "ExecutionSuccess"); + describe('Enabled as a Module', () => { + it('Emits an ExecutionSuccess event', async () => { + await expect(enableModuleTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an EnabledModule event", async () => { + it('Emits an EnabledModule event', async () => { await expect(enableModuleTx) - .to.emit(gnosisSafe, "EnabledModule") + .to.emit(gnosisSafe, 'EnabledModule') .withArgs(decentSablierManagementAddress); }); }); - describe("Withdrawing From Stream", () => { + describe('Withdrawing From Stream', () => { let withdrawTx: ethers.ContractTransactionResponse; - describe("When the stream has funds", () => { + describe('When the stream has funds', () => { beforeEach(async () => { // Advance time to the end of the stream - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 2592000, ]); - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); // No action has been taken yet on the stream. Balance should be untouched. - expect(await mockSablier.withdrawableAmountOf(streamId)).to.eq( - streamFundsMax - ); + expect(await mockSablier.withdrawableAmountOf(streamId)).to.eq(streamFundsMax); const recipientHatAccount = await getHatAccount( 2n, erc6551Registry, mockHatsAccountImplementationAddress, mockHatsAddress, - dao + dao, ); withdrawTx = await executeSafeTransaction({ @@ -284,60 +247,55 @@ describe("DecentSablierStreamManagement", () => { to: decentSablierManagementAddress, transactionData: DecentSablierStreamManagement__factory.createInterface().encodeFunctionData( - "withdrawMaxFromStream", - [ - mockSablierAddress, - await recipientHatAccount.getAddress(), - streamId, - dao.address, - ] + 'withdrawMaxFromStream', + [mockSablierAddress, await recipientHatAccount.getAddress(), streamId, dao.address], ), signers: [dao], }); - expect(withdrawTx).to.not.reverted; + await expect(withdrawTx).to.not.be.reverted; }); - it("Emits an ExecutionSuccess event", async () => { - await expect(withdrawTx).to.emit(gnosisSafe, "ExecutionSuccess"); + it('Emits an ExecutionSuccess event', async () => { + await expect(withdrawTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an ExecutionFromModuleSuccess event", async () => { + it('Emits an ExecutionFromModuleSuccess event', async () => { await expect(withdrawTx) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .to.emit(gnosisSafe, 'ExecutionFromModuleSuccess') .withArgs(decentSablierManagementAddress); }); - it("Withdraws the maximum amount from the stream", async () => { + it('Withdraws the maximum amount from the stream', async () => { expect(await mockSablier.withdrawableAmountOf(streamId)).to.equal(0); }); }); - describe("When the stream has no funds", () => { + describe('When the stream has no funds', () => { beforeEach(async () => { // Advance time to the end of the stream - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 2592000, ]); - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); const recipientHatAccount = await getHatAccount( 2n, erc6551Registry, mockHatsAccountImplementationAddress, mockHatsAddress, - dao + dao, ); // The recipient withdraws the full amount await recipientHatAccount.execute( mockSablierAddress, 0n, - MockSablierV2LockupLinear__factory.createInterface().encodeFunctionData( - "withdrawMax", - [streamId, dao.address] - ), - 0 + MockSablierV2LockupLinear__factory.createInterface().encodeFunctionData('withdrawMax', [ + streamId, + dao.address, + ]), + 0, ); expect(await mockSablier.withdrawableAmountOf(streamId)).to.equal(0); @@ -347,116 +305,105 @@ describe("DecentSablierStreamManagement", () => { to: decentSablierManagementAddress, transactionData: DecentSablierStreamManagement__factory.createInterface().encodeFunctionData( - "withdrawMaxFromStream", - [ - mockSablierAddress, - await recipientHatAccount.getAddress(), - streamId, - dao.address, - ] + 'withdrawMaxFromStream', + [mockSablierAddress, await recipientHatAccount.getAddress(), streamId, dao.address], ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(withdrawTx).to.emit(gnosisSafe, "ExecutionSuccess"); + it('Emits an ExecutionSuccess event', async () => { + await expect(withdrawTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Does not emit an ExecutionFromModuleSuccess event", async () => { - await expect(withdrawTx).to.not.emit( - gnosisSafe, - "ExecutionFromModuleSuccess" - ); + it('Does not emit an ExecutionFromModuleSuccess event', async () => { + await expect(withdrawTx).to.not.emit(gnosisSafe, 'ExecutionFromModuleSuccess'); }); - it("Does not revert", async () => { - expect(withdrawTx).to.not.reverted; + it('Does not revert', async () => { + await expect(withdrawTx).to.not.be.reverted; }); }); }); - describe("Cancelling From Stream", () => { + describe('Cancelling From Stream', () => { let cancelTx: ethers.ContractTransactionResponse; - describe("When the stream is active", () => { + describe('When the stream is active', () => { beforeEach(async () => { // Advance time to before the end of the stream - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 60000, ]); // 1 minute from now - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); cancelTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentSablierManagementAddress, transactionData: DecentSablierStreamManagement__factory.createInterface().encodeFunctionData( - "cancelStream", - [mockSablierAddress, streamId] + 'cancelStream', + [mockSablierAddress, streamId], ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(cancelTx).to.emit(gnosisSafe, "ExecutionSuccess"); + it('Emits an ExecutionSuccess event', async () => { + await expect(cancelTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Emits an ExecutionFromModuleSuccess event", async () => { + it('Emits an ExecutionFromModuleSuccess event', async () => { await expect(cancelTx) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .to.emit(gnosisSafe, 'ExecutionFromModuleSuccess') .withArgs(decentSablierManagementAddress); }); - it("Cancels the stream", async () => { + it('Cancels the stream', async () => { expect(await mockSablier.statusOf(streamId)).to.equal(3); // 3 === LockupLinear.Status.CANCELED }); }); - describe("When the stream has expired", () => { + describe('When the stream has expired', () => { beforeEach(async () => { // Advance time to the end of the stream - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 2592000 + 60000, ]); // 30 days from now + 1 minute - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); cancelTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentSablierManagementAddress, transactionData: DecentSablierStreamManagement__factory.createInterface().encodeFunctionData( - "cancelStream", - [mockSablierAddress, streamId] + 'cancelStream', + [mockSablierAddress, streamId], ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(cancelTx).to.emit(gnosisSafe, "ExecutionSuccess"); + it('Emits an ExecutionSuccess event', async () => { + await expect(cancelTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Does not emit an ExecutionFromModuleSuccess event", async () => { - await expect(cancelTx).to.not.emit( - gnosisSafe, - "ExecutionFromModuleSuccess" - ); + it('Does not emit an ExecutionFromModuleSuccess event', async () => { + await expect(cancelTx).to.not.emit(gnosisSafe, 'ExecutionFromModuleSuccess'); }); - it("Does not revert", async () => { - expect(cancelTx).to.not.reverted; + it('Does not revert', async () => { + await expect(cancelTx).to.not.be.reverted; }); }); - describe("When the stream has been previously cancelled", () => { + describe('When the stream has been previously cancelled', () => { beforeEach(async () => { // Advance time to before the end of the stream - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 120000, ]); // 2 minutes from now - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); const stream = await mockSablier.getStream(streamId); expect(stream.endTime).to.be.greaterThan(currentBlockTimestamp); @@ -465,44 +412,40 @@ describe("DecentSablierStreamManagement", () => { await executeSafeTransaction({ safe: gnosisSafe, to: mockSablierAddress, - transactionData: - MockSablierV2LockupLinear__factory.createInterface().encodeFunctionData( - "cancel", - [streamId] - ), + transactionData: MockSablierV2LockupLinear__factory.createInterface().encodeFunctionData( + 'cancel', + [streamId], + ), signers: [dao], }); - await hre.ethers.provider.send("evm_setNextBlockTimestamp", [ + await hre.ethers.provider.send('evm_setNextBlockTimestamp', [ currentBlockTimestamp + 240000, ]); // 4 minutes from now - await hre.ethers.provider.send("evm_mine", []); + await hre.ethers.provider.send('evm_mine', []); cancelTx = await executeSafeTransaction({ safe: gnosisSafe, to: decentSablierManagementAddress, transactionData: DecentSablierStreamManagement__factory.createInterface().encodeFunctionData( - "cancelStream", - [mockSablierAddress, streamId] + 'cancelStream', + [mockSablierAddress, streamId], ), signers: [dao], }); }); - it("Emits an ExecutionSuccess event", async () => { - await expect(cancelTx).to.emit(gnosisSafe, "ExecutionSuccess"); + it('Emits an ExecutionSuccess event', async () => { + await expect(cancelTx).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Does not emit an ExecutionFromModuleSuccess event", async () => { - await expect(cancelTx).to.not.emit( - gnosisSafe, - "ExecutionFromModuleSuccess" - ); + it('Does not emit an ExecutionFromModuleSuccess event', async () => { + await expect(cancelTx).to.not.emit(gnosisSafe, 'ExecutionFromModuleSuccess'); }); - it("Does not revert", async () => { - expect(cancelTx).to.not.reverted; + it('Does not revert', async () => { + await expect(cancelTx).to.not.be.reverted; }); }); }); diff --git a/test/ERC20-Claim.test.ts b/test/ERC20-Claim.test.ts index 4def7119..798f5618 100644 --- a/test/ERC20-Claim.test.ts +++ b/test/ERC20-Claim.test.ts @@ -1,21 +1,20 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import chai from 'chai'; +import hre, { ethers } from 'hardhat'; import { VotesERC20, VotesERC20__factory, ERC20Claim, ERC20Claim__factory, ModuleProxyFactory, -} from "../typechain-types"; -import chai from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; -import time from "./time"; -import { calculateProxyAddress } from "./helpers"; -import { getModuleProxyFactory } from "./GlobalSafeDeployments.test"; +} from '../typechain-types'; +import { getModuleProxyFactory } from './GlobalSafeDeployments.test'; +import { calculateProxyAddress } from './helpers'; +import time from './time'; const expect = chai.expect; -describe("ERC-20 Token Claiming", function () { +describe('ERC-20 Token Claiming', function () { let moduleProxyFactory: ModuleProxyFactory; let votesERC20Mastercopy: VotesERC20; let parentERC20: VotesERC20; @@ -39,82 +38,76 @@ describe("ERC-20 Token Claiming", function () { const parentERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "ParentDecent", - "pDCNT", + 'ParentDecent', + 'pDCNT', [deployer.address, userA.address], - [ethers.parseUnits("100", 18), ethers.parseUnits("150", 18)], - ] + [ethers.parseUnits('100', 18), ethers.parseUnits('150', 18)], + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), parentERC20SetupData, - "10031021" + '10031021', ); const predictedParentVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), parentERC20SetupData, - "10031021" + '10031021', ); - parentERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedParentVotesERC20Address - ); + parentERC20 = await hre.ethers.getContractAt('VotesERC20', predictedParentVotesERC20Address); const childERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "ChildDecent", - "cDCNT", + 'ChildDecent', + 'cDCNT', [userB.address, deployer.address], - [ethers.parseUnits("100", 18), ethers.parseUnits("100", 18)], - ] + [ethers.parseUnits('100', 18), ethers.parseUnits('100', 18)], + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), childERC20SetupData, - "10031021" + '10031021', ); const predictedChildVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), childERC20SetupData, - "10031021" + '10031021', ); - childERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedChildVotesERC20Address - ); + childERC20 = await hre.ethers.getContractAt('VotesERC20', predictedChildVotesERC20Address); - const latestBlock = await hre.ethers.provider.getBlock("latest"); + const latestBlock = await hre.ethers.provider.getBlock('latest'); const erc20ClaimSetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["uint32", "address", "address", "address", "uint256"], + ['uint32', 'address', 'address', 'address', 'uint256'], [ latestBlock!.number + 5, deployer.address, await parentERC20.getAddress(), await childERC20.getAddress(), - ethers.parseUnits("100", 18), - ] + ethers.parseUnits('100', 18), + ], ), ]); @@ -122,165 +115,147 @@ describe("ERC-20 Token Claiming", function () { moduleProxyFactory, await erc20ClaimMastercopy.getAddress(), erc20ClaimSetupData, - "10031021" + '10031021', ); await childERC20 .connect(deployer) - .approve(predictedERC20ClaimAddress, ethers.parseUnits("100", 18)); + .approve(predictedERC20ClaimAddress, ethers.parseUnits('100', 18)); await moduleProxyFactory.deployModule( await erc20ClaimMastercopy.getAddress(), erc20ClaimSetupData, - "10031021" + '10031021', ); - erc20Claim = await hre.ethers.getContractAt( - "ERC20Claim", - predictedERC20ClaimAddress - ); + erc20Claim = await hre.ethers.getContractAt('ERC20Claim', predictedERC20ClaimAddress); }); - it("Init is correct", async () => { - expect(await parentERC20.name()).to.eq("ParentDecent"); - expect(await parentERC20.symbol()).to.eq("pDCNT"); - expect(await parentERC20.totalSupply()).to.eq(ethers.parseUnits("250", 18)); - expect(await parentERC20.balanceOf(deployer.address)).to.eq( - ethers.parseUnits("100", 18) - ); - expect(await parentERC20.balanceOf(userA.address)).to.eq( - ethers.parseUnits("150", 18) - ); - - expect(await childERC20.name()).to.eq("ChildDecent"); - expect(await childERC20.symbol()).to.eq("cDCNT"); - expect(await childERC20.totalSupply()).to.eq(ethers.parseUnits("200", 18)); - expect(await childERC20.balanceOf(userB.address)).to.eq( - ethers.parseUnits("100", 18) - ); - expect(await childERC20.balanceOf(deployer.address)).to.eq( - ethers.parseUnits("0", 18) - ); + it('Init is correct', async () => { + expect(await parentERC20.name()).to.eq('ParentDecent'); + expect(await parentERC20.symbol()).to.eq('pDCNT'); + expect(await parentERC20.totalSupply()).to.eq(ethers.parseUnits('250', 18)); + expect(await parentERC20.balanceOf(deployer.address)).to.eq(ethers.parseUnits('100', 18)); + expect(await parentERC20.balanceOf(userA.address)).to.eq(ethers.parseUnits('150', 18)); + + expect(await childERC20.name()).to.eq('ChildDecent'); + expect(await childERC20.symbol()).to.eq('cDCNT'); + expect(await childERC20.totalSupply()).to.eq(ethers.parseUnits('200', 18)); + expect(await childERC20.balanceOf(userB.address)).to.eq(ethers.parseUnits('100', 18)); + expect(await childERC20.balanceOf(deployer.address)).to.eq(ethers.parseUnits('0', 18)); expect(await childERC20.balanceOf(await erc20Claim.getAddress())).to.eq( - ethers.parseUnits("100", 18) + ethers.parseUnits('100', 18), ); }); - it("Inits ClaimSubsidiary contract", async () => { + it('Inits ClaimSubsidiary contract', async () => { expect(await erc20Claim.childERC20()).to.eq(await childERC20.getAddress()); - expect(await erc20Claim.parentERC20()).to.eq( - await parentERC20.getAddress() - ); + expect(await erc20Claim.parentERC20()).to.eq(await parentERC20.getAddress()); expect(await erc20Claim.snapShotId()).to.eq(1); - expect(await erc20Claim.parentAllocation()).to.eq( - ethers.parseUnits("100", 18) - ); + expect(await erc20Claim.parentAllocation()).to.eq(ethers.parseUnits('100', 18)); }); - it("Claim Snap", async () => { + it('Claim Snap', async () => { const amount = await erc20Claim.getClaimAmount(deployer.address); // Claim on behalf - await expect( - erc20Claim.connect(userB).claimTokens(deployer.address) - ).to.emit(erc20Claim, "ERC20Claimed"); + await expect(erc20Claim.connect(userB).claimTokens(deployer.address)).to.emit( + erc20Claim, + 'ERC20Claimed', + ); expect( amount + (await erc20Claim.getClaimAmount(userA.address)) + - (await erc20Claim.getClaimAmount(await erc20Claim.getAddress())) - ).to.eq(ethers.parseUnits("100", 18)); + (await erc20Claim.getClaimAmount(await erc20Claim.getAddress())), + ).to.eq(ethers.parseUnits('100', 18)); expect(await childERC20.balanceOf(deployer.address)).to.eq(amount); expect(await childERC20.balanceOf(await erc20Claim.getAddress())).to.eq( - ethers.parseUnits("100", 18) - amount + ethers.parseUnits('100', 18) - amount, ); }); - it("Should revert double claim", async () => { - await expect(erc20Claim.claimTokens(deployer.address)).to.emit( - erc20Claim, - "ERC20Claimed" - ); + it('Should revert double claim', async () => { + await expect(erc20Claim.claimTokens(deployer.address)).to.emit(erc20Claim, 'ERC20Claimed'); expect(await erc20Claim.getClaimAmount(deployer.address)).to.eq(0); await expect( - erc20Claim.connect(userA).claimTokens(deployer.address) - ).to.revertedWithCustomError(erc20Claim, "NoAllocation"); - await expect( - erc20Claim.claimTokens(deployer.address) - ).to.revertedWithCustomError(erc20Claim, "NoAllocation"); + erc20Claim.connect(userA).claimTokens(deployer.address), + ).to.revertedWithCustomError(erc20Claim, 'NoAllocation'); + await expect(erc20Claim.claimTokens(deployer.address)).to.revertedWithCustomError( + erc20Claim, + 'NoAllocation', + ); }); - it("Should revert without an allocation", async () => { - await expect( - erc20Claim.claimTokens(userB.address) - ).to.revertedWithCustomError(erc20Claim, "NoAllocation"); + it('Should revert without an allocation', async () => { + await expect(erc20Claim.claimTokens(userB.address)).to.revertedWithCustomError( + erc20Claim, + 'NoAllocation', + ); }); - it("Should revert a non funder reclaim", async () => { - await expect( - erc20Claim.connect(userA).reclaim() - ).to.revertedWithCustomError(erc20Claim, "NotTheFunder"); + it('Should revert a non funder reclaim', async () => { + await expect(erc20Claim.connect(userA).reclaim()).to.revertedWithCustomError( + erc20Claim, + 'NotTheFunder', + ); }); - it("Should revert an unexpired reclaim", async () => { - await expect( - erc20Claim.connect(deployer).reclaim() - ).to.revertedWithCustomError(erc20Claim, "DeadlinePending"); + it('Should revert an unexpired reclaim', async () => { + await expect(erc20Claim.connect(deployer).reclaim()).to.revertedWithCustomError( + erc20Claim, + 'DeadlinePending', + ); }); - it("Should allow an expired reclaim", async () => { + it('Should allow an expired reclaim', async () => { await time.advanceBlocks(5); await erc20Claim.connect(deployer).reclaim(); - expect(await childERC20.balanceOf(deployer.address)).to.eq( - ethers.parseUnits("100", 18) - ); + expect(await childERC20.balanceOf(deployer.address)).to.eq(ethers.parseUnits('100', 18)); }); - it("If the deadlineBlock is setup as zero, then calling reclaim will revert", async () => { + it('If the deadlineBlock is setup as zero, then calling reclaim will revert', async () => { const abiCoder2 = new ethers.AbiCoder(); const childERC20SetupData2 = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder2.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "ChildDecent", - "cDCNT", + 'ChildDecent', + 'cDCNT', [userB.address, deployer.address], - [ethers.parseUnits("200", 18), ethers.parseUnits("200", 18)], - ] + [ethers.parseUnits('200', 18), ethers.parseUnits('200', 18)], + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), childERC20SetupData2, - "10031021" + '10031021', ); const predictedChildVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), childERC20SetupData2, - "10031021" + '10031021', ); - childERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedChildVotesERC20Address - ); + childERC20 = await hre.ethers.getContractAt('VotesERC20', predictedChildVotesERC20Address); const erc20ClaimSetupData2 = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder2.encode( - ["uint32", "address", "address", "address", "uint256"], + ['uint32', 'address', 'address', 'address', 'uint256'], [ 0, deployer.address, await parentERC20.getAddress(), await childERC20.getAddress(), - ethers.parseUnits("100", 18), - ] + ethers.parseUnits('100', 18), + ], ), ]); @@ -288,26 +263,24 @@ describe("ERC-20 Token Claiming", function () { moduleProxyFactory, await erc20ClaimMastercopy.getAddress(), erc20ClaimSetupData2, - "10031021" + '10031021', ); await childERC20 .connect(deployer) - .approve(predictedERC20ClaimAddress, ethers.parseUnits("100", 18)); + .approve(predictedERC20ClaimAddress, ethers.parseUnits('100', 18)); await moduleProxyFactory.deployModule( await erc20ClaimMastercopy.getAddress(), erc20ClaimSetupData2, - "10031021" + '10031021', ); - erc20Claim = await hre.ethers.getContractAt( - "ERC20Claim", - predictedERC20ClaimAddress - ); + erc20Claim = await hre.ethers.getContractAt('ERC20Claim', predictedERC20ClaimAddress); - await expect( - erc20Claim.connect(deployer).reclaim() - ).to.be.revertedWithCustomError(erc20Claim, "NoDeadline"); + await expect(erc20Claim.connect(deployer).reclaim()).to.be.revertedWithCustomError( + erc20Claim, + 'NoDeadline', + ); }); }); diff --git a/test/Fractal-Module.test.ts b/test/Fractal-Module.test.ts index bf37b15b..75de7dea 100644 --- a/test/Fractal-Module.test.ts +++ b/test/Fractal-Module.test.ts @@ -1,7 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { VotesERC20__factory, FractalModule, @@ -14,22 +13,22 @@ import { GnosisSafeL2__factory, MultiSendCallOnly__factory, MultiSendCallOnly, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, + getMultiSendCallOnly, +} from './GlobalSafeDeployments.test'; import { calculateProxyAddress, predictGnosisSafeAddress, buildContractCall, MetaTransaction, encodeMultiSend, -} from "./helpers"; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, - getMultiSendCallOnly, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; -describe("Fractal Module Tests", () => { +describe('Fractal Module Tests', () => { let gnosisSafeProxyFactory: GnosisSafeProxyFactory; let moduleProxyFactory: ModuleProxyFactory; let gnosisSafeL2Singleton: GnosisSafeL2; @@ -52,9 +51,7 @@ describe("Fractal Module Tests", () => { let freezeGuardSetup: string; let setModuleCalldata: string; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { [deployer, owner1, owner2, owner3] = await hre.ethers.getSigners(); @@ -68,13 +65,8 @@ describe("Fractal Module Tests", () => { // SETUP GnosisSafe createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [ - owner1.address, - owner2.address, - owner3.address, - await multiSendCallOnly.getAddress(), - ], + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ + [owner1.address, owner2.address, owner3.address, await multiSendCallOnly.getAddress()], 1, ethers.ZeroAddress, ethers.ZeroHash, @@ -87,36 +79,24 @@ describe("Fractal Module Tests", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Get Gnosis Safe contract // eslint-disable-next-line camelcase - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); /// ///////////// GUARD /////////////////// // DEPLOY GUARD freezeGuard = await new MultisigFreezeGuard__factory(deployer).deploy(); freezeGuardSetup = // eslint-disable-next-line camelcase - MultisigFreezeGuard__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["uint256", "uint256", "address", "address", "address"], - [ - 10, - 10, - owner1.address, - owner1.address, - await gnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeGuard__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['uint256', 'uint256', 'address', 'address', 'address'], + [10, 10, owner1.address, owner1.address, await gnosisSafe.getAddress()], + ), + ]); /// /////////////// MODULE //////////////// // DEPLOY Fractal Module @@ -125,15 +105,15 @@ describe("Fractal Module Tests", () => { // SETUP Module setModuleCalldata = // eslint-disable-next-line camelcase - FractalModule__factory.createInterface().encodeFunctionData("setUp", [ + FractalModule__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]"], + ['address', 'address', 'address', 'address[]'], [ owner1.address, await gnosisSafe.getAddress(), await gnosisSafe.getAddress(), [owner2.address], - ] + ], ), ]); @@ -141,239 +121,208 @@ describe("Fractal Module Tests", () => { moduleProxyFactory, await moduleImpl.getAddress(), setModuleCalldata, - "10031021" + '10031021', ); - fractalModule = await hre.ethers.getContractAt( - "FractalModule", - predictedFractalModule - ); + fractalModule = await hre.ethers.getContractAt('FractalModule', predictedFractalModule); }); - describe("Fractal Module", () => { - it("Supports the expected ERC165 interface", async () => { + describe('Fractal Module', () => { + it('Supports the expected ERC165 interface', async () => { const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [await moduleImpl.getAddress(), setModuleCalldata, "10031021"], + 'deployModule', + [await moduleImpl.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await expect(multiSendCallOnly.multiSend(safeTx)) - .to.emit(gnosisSafeProxyFactory, "ProxyCreation") - .withArgs( - await gnosisSafe.getAddress(), - await gnosisSafeL2Singleton.getAddress() - ); + .to.emit(gnosisSafeProxyFactory, 'ProxyCreation') + .withArgs(await gnosisSafe.getAddress(), await gnosisSafeL2Singleton.getAddress()); }); - it("Owner may add/remove controllers", async () => { + it('Owner may add/remove controllers', async () => { const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [await moduleImpl.getAddress(), setModuleCalldata, "10031021"], + 'deployModule', + [await moduleImpl.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await multiSendCallOnly.multiSend(safeTx); // ADD Controller - await expect( - fractalModule.connect(owner3).addControllers([owner3.address]) - ).to.revertedWith("Ownable: caller is not the owner"); + await expect(fractalModule.connect(owner3).addControllers([owner3.address])).to.revertedWith( + 'Ownable: caller is not the owner', + ); expect(await fractalModule.controllers(owner3.address)).eq(false); - await expect( - fractalModule.connect(owner1).addControllers([owner3.address]) - ).to.emit(fractalModule, "ControllersAdded"); + await expect(fractalModule.connect(owner1).addControllers([owner3.address])).to.emit( + fractalModule, + 'ControllersAdded', + ); expect(await fractalModule.controllers(owner3.address)).eq(true); // REMOVE Controller await expect( - fractalModule.connect(owner3).removeControllers([owner3.address]) - ).to.revertedWith("Ownable: caller is not the owner"); + fractalModule.connect(owner3).removeControllers([owner3.address]), + ).to.revertedWith('Ownable: caller is not the owner'); expect(await fractalModule.controllers(owner3.address)).eq(true); - await expect( - fractalModule.connect(owner1).removeControllers([owner3.address]) - ).to.emit(fractalModule, "ControllersRemoved"); + await expect(fractalModule.connect(owner1).removeControllers([owner3.address])).to.emit( + fractalModule, + 'ControllersRemoved', + ); expect(await fractalModule.controllers(owner3.address)).eq(false); }); - it("Authorized users may exec TXs", async () => { + it('Authorized users may exec TXs', async () => { const internalTxs: MetaTransaction[] = [ await buildContractCall( gnosisSafe, - "enableModule", + 'enableModule', [await fractalModule.getAddress()], 0, - false + false, ), ]; const safeInternalTx = encodeMultiSend(internalTxs); const sigs = - "0x000000000000000000000000" + + '0x000000000000000000000000' + (await multiSendCallOnly.getAddress()).slice(2) + - "0000000000000000000000000000000000000000000000000000000000000000" + - "01"; + '0000000000000000000000000000000000000000000000000000000000000000' + + '01'; const txs: MetaTransaction[] = [ await buildContractCall( gnosisSafeProxyFactory, - "createProxyWithNonce", - [ - await gnosisSafeL2Singleton.getAddress(), - createGnosisSetupCalldata, - saltNum, - ], + 'createProxyWithNonce', + [await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, saltNum], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [await moduleImpl.getAddress(), setModuleCalldata, "10031021"], + 'deployModule', + [await moduleImpl.getAddress(), setModuleCalldata, '10031021'], 0, - false + false, ), await buildContractCall( moduleProxyFactory, - "deployModule", - [await freezeGuard.getAddress(), freezeGuardSetup, "10031021"], + 'deployModule', + [await freezeGuard.getAddress(), freezeGuardSetup, '10031021'], 0, - false + false, ), await buildContractCall( gnosisSafe, - "execTransaction", + 'execTransaction', [ await multiSendCallOnly.getAddress(), // to - "0", // value + '0', // value // eslint-disable-next-line camelcase - MultiSendCallOnly__factory.createInterface().encodeFunctionData( - "multiSend", - [safeInternalTx] - ), // calldata - "1", // operation - "0", // tx gas - "0", // base gas - "0", // gas price + MultiSendCallOnly__factory.createInterface().encodeFunctionData('multiSend', [ + safeInternalTx, + ]), // calldata + '1', // operation + '0', // tx gas + '0', // base gas + '0', // gas price ethers.ZeroAddress, // gas token ethers.ZeroAddress, // receiver sigs, // sigs ], 0, - false + false, ), ]; const safeTx = encodeMultiSend(txs); await multiSendCallOnly.multiSend(safeTx); - // FUND SAFE - const abiCoder = new ethers.AbiCoder(); // encode data - // Deploy token mastercopy - const votesERC20Mastercopy = await new VotesERC20__factory( - deployer - ).deploy(); + const votesERC20Mastercopy = await new VotesERC20__factory(deployer).deploy(); const votesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], - ["DCNT", "DCNT", [await gnosisSafe.getAddress()], [1000]] + ['string', 'string', 'address[]', 'uint256[]'], + ['DCNT', 'DCNT', [await gnosisSafe.getAddress()], [1000]], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); const predictedVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); - const votesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedVotesERC20Address - ); + const votesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedVotesERC20Address); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 1000 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(1000); expect(await votesERC20.balanceOf(owner1.address)).to.eq(0); // CLAWBACK FUNDS const clawBackCalldata = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("transfer", [ - owner1.address, - 500, - ]); + VotesERC20__factory.createInterface().encodeFunctionData('transfer', [owner1.address, 500]); const txData = // eslint-disable-next-line camelcase abiCoder.encode( - ["address", "uint256", "bytes", "uint8"], - [await votesERC20.getAddress(), 0, clawBackCalldata, 0] + ['address', 'uint256', 'bytes', 'uint8'], + [await votesERC20.getAddress(), 0, clawBackCalldata, 0], ); // REVERT => NOT AUTHORIZED await expect(fractalModule.execTx(txData)).to.be.revertedWithCustomError( fractalModule, - "Unauthorized" + 'Unauthorized', ); // OWNER MAY EXECUTE await expect(fractalModule.connect(owner1).execTx(txData)).to.emit( gnosisSafe, - "ExecutionFromModuleSuccess" + 'ExecutionFromModuleSuccess', ); // Controller MAY EXECUTE await expect(fractalModule.connect(owner2).execTx(txData)).to.emit( gnosisSafe, - "ExecutionFromModuleSuccess" + 'ExecutionFromModuleSuccess', ); // REVERT => Execution Failure - await expect( - fractalModule.connect(owner1).execTx(txData) - ).to.be.revertedWithCustomError(fractalModule, "TxFailed"); - - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 0 + await expect(fractalModule.connect(owner1).execTx(txData)).to.be.revertedWithCustomError( + fractalModule, + 'TxFailed', ); + + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(owner1.address)).to.eq(1000); }); }); diff --git a/test/Fractal-Registry.test.ts b/test/Fractal-Registry.test.ts index 1d046fc0..f05ed7f6 100644 --- a/test/Fractal-Registry.test.ts +++ b/test/Fractal-Registry.test.ts @@ -1,15 +1,15 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre from 'hardhat'; import { FractalRegistry, FractalRegistry__factory, KeyValuePairs, KeyValuePairs__factory, -} from "../typechain-types"; +} from '../typechain-types'; -describe("Fractal Registry", () => { +describe('Fractal Registry', () => { // Deployed contracts let fractalRegistry: FractalRegistry; let keyValues: KeyValuePairs; @@ -27,43 +27,41 @@ describe("Fractal Registry", () => { keyValues = await new KeyValuePairs__factory(deployer).deploy(); }); - it("A DAO can update its name", async () => { - await expect(fractalRegistry.connect(dao1).updateDAOName("Decent Dawgs")) - .to.emit(fractalRegistry, "FractalNameUpdated") - .withArgs(dao1.address, "Decent Dawgs"); + it('A DAO can update its name', async () => { + await expect(fractalRegistry.connect(dao1).updateDAOName('Decent Dawgs')) + .to.emit(fractalRegistry, 'FractalNameUpdated') + .withArgs(dao1.address, 'Decent Dawgs'); - await expect(fractalRegistry.connect(dao2).updateDAOName("Decent Dawgs2")) - .to.emit(fractalRegistry, "FractalNameUpdated") - .withArgs(dao2.address, "Decent Dawgs2"); + await expect(fractalRegistry.connect(dao2).updateDAOName('Decent Dawgs2')) + .to.emit(fractalRegistry, 'FractalNameUpdated') + .withArgs(dao2.address, 'Decent Dawgs2'); }); - it("A DAO can update its name multiple times", async () => { - await expect(fractalRegistry.connect(dao1).updateDAOName("Decent Dawgs")) - .to.emit(fractalRegistry, "FractalNameUpdated") - .withArgs(dao1.address, "Decent Dawgs"); + it('A DAO can update its name multiple times', async () => { + await expect(fractalRegistry.connect(dao1).updateDAOName('Decent Dawgs')) + .to.emit(fractalRegistry, 'FractalNameUpdated') + .withArgs(dao1.address, 'Decent Dawgs'); - await expect(fractalRegistry.connect(dao1).updateDAOName("Decent Dawgs2")) - .to.emit(fractalRegistry, "FractalNameUpdated") - .withArgs(dao1.address, "Decent Dawgs2"); + await expect(fractalRegistry.connect(dao1).updateDAOName('Decent Dawgs2')) + .to.emit(fractalRegistry, 'FractalNameUpdated') + .withArgs(dao1.address, 'Decent Dawgs2'); }); - it("A DAO can declare its subDAO", async () => { + it('A DAO can declare its subDAO', async () => { await expect(fractalRegistry.connect(dao1).declareSubDAO(dao2.address)) - .to.emit(fractalRegistry, "FractalSubDAODeclared") + .to.emit(fractalRegistry, 'FractalSubDAODeclared') .withArgs(dao1.address, dao2.address); }); - it("A DAO can declare arbitrary key/value pairs", async () => { - await expect( - keyValues.connect(dao1).updateValues(["twitter"], ["@awesome"]) - ) - .to.emit(keyValues, "ValueUpdated") - .withArgs(dao1.address, "twitter", "@awesome"); + it('A DAO can declare arbitrary key/value pairs', async () => { + await expect(keyValues.connect(dao1).updateValues(['twitter'], ['@awesome'])) + .to.emit(keyValues, 'ValueUpdated') + .withArgs(dao1.address, 'twitter', '@awesome'); }); - it("KeyValuePairs reverts if unequal array lengths are passed to it", async () => { + it('KeyValuePairs reverts if unequal array lengths are passed to it', async () => { await expect( - keyValues.connect(dao1).updateValues(["twitter", "discord"], ["@awesome"]) - ).to.be.revertedWithCustomError(keyValues, "IncorrectValueCount"); + keyValues.connect(dao1).updateValues(['twitter', 'discord'], ['@awesome']), + ).to.be.revertedWithCustomError(keyValues, 'IncorrectValueCount'); }); }); diff --git a/test/GlobalSafeDeployments.test.ts b/test/GlobalSafeDeployments.test.ts index c9cb0144..30411035 100644 --- a/test/GlobalSafeDeployments.test.ts +++ b/test/GlobalSafeDeployments.test.ts @@ -1,3 +1,4 @@ +import hre from 'hardhat'; import { GnosisSafeProxyFactory, GnosisSafeProxyFactory__factory, @@ -9,8 +10,7 @@ import { GnosisSafeL2__factory, MockContract, MockContract__factory, -} from "../typechain-types"; -import hre from "hardhat"; +} from '../typechain-types'; let gnosisSafeProxyFactory: GnosisSafeProxyFactory; let moduleProxyFactory: ModuleProxyFactory; @@ -21,9 +21,7 @@ let mockContract: MockContract; beforeEach(async () => { const [deployer] = await hre.ethers.getSigners(); - gnosisSafeProxyFactory = await new GnosisSafeProxyFactory__factory( - deployer - ).deploy(); + gnosisSafeProxyFactory = await new GnosisSafeProxyFactory__factory(deployer).deploy(); moduleProxyFactory = await new ModuleProxyFactory__factory(deployer).deploy(); gnosisSafeL2Singleton = await new GnosisSafeL2__factory(deployer).deploy(); multiSendCallOnly = await new MultiSendCallOnly__factory(deployer).deploy(); diff --git a/test/MultisigFreezeGuard-ERC20FreezeVoting.test.ts b/test/MultisigFreezeGuard-ERC20FreezeVoting.test.ts index c355d6ea..9eaab44d 100644 --- a/test/MultisigFreezeGuard-ERC20FreezeVoting.test.ts +++ b/test/MultisigFreezeGuard-ERC20FreezeVoting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { VotesERC20, VotesERC20__factory, @@ -12,21 +10,22 @@ import { MultisigFreezeGuard__factory, GnosisSafeL2__factory, GnosisSafeL2, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; +import time from './time'; -describe("Child Multisig DAO with Azorius Parent", () => { +describe('Child Multisig DAO with Azorius Parent', () => { // Deployed contracts let gnosisSafe: GnosisSafeL2; let freezeGuardMastercopy: MultisigFreezeGuard; @@ -49,20 +48,11 @@ describe("Child Multisig DAO with Azorius Parent", () => { let createGnosisSetupCalldata: string; const threshold = 2; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { - [ - deployer, - owner1, - owner2, - owner3, - tokenVetoer1, - tokenVetoer2, - freezeGuardOwner, - ] = await hre.ethers.getSigners(); + [deployer, owner1, owner2, owner3, tokenVetoer1, tokenVetoer2, freezeGuardOwner] = + await hre.ethers.getSigners(); const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); const moduleProxyFactory = getModuleProxyFactory(); @@ -70,7 +60,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [owner1.address, owner2.address, owner3.address], threshold, ethers.ZeroAddress, @@ -85,22 +75,19 @@ describe("Child Multisig DAO with Azorius Parent", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, - saltNum + saltNum, ); // Get Gnosis Safe contract // eslint-disable-next-line camelcase - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); // Deploy token mastercopy votesERC20Mastercopy = await new VotesERC20__factory(deployer).deploy(); @@ -108,127 +95,113 @@ describe("Child Multisig DAO with Azorius Parent", () => { const abiCoder = new ethers.AbiCoder(); // encode data const votesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], + ['string', 'string', 'address[]', 'uint256[]'], [ - "DCNT", - "DCNT", - [ - tokenVetoer1.address, - tokenVetoer2.address, - await gnosisSafe.getAddress(), - ], + 'DCNT', + 'DCNT', + [tokenVetoer1.address, tokenVetoer2.address, await gnosisSafe.getAddress()], [500, 600, 1000], - ] + ], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); const predictedVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); - votesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedVotesERC20Address - ); + votesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedVotesERC20Address); // Vetoers delegate their votes to themselves await votesERC20.connect(tokenVetoer1).delegate(tokenVetoer1.address); await votesERC20.connect(tokenVetoer2).delegate(tokenVetoer2.address); // Deploy ERC20FreezeVoting mastercopy contract - freezeVotingMastercopy = await new ERC20FreezeVoting__factory( - deployer - ).deploy(); + freezeVotingMastercopy = await new ERC20FreezeVoting__factory(deployer).deploy(); // Initialize FreezeVoting contract const freezeVotingSetupData = // eslint-disable-next-line camelcase - ERC20FreezeVoting__factory.createInterface().encodeFunctionData("setUp", [ + ERC20FreezeVoting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "uint256", "uint32", "uint32", "address"], + ['address', 'uint256', 'uint32', 'uint32', 'address'], [ freezeGuardOwner.address, 1090, // freeze votes threshold 10, // freeze proposal period 200, // freeze period await votesERC20.getAddress(), - ] + ], ), ]); await moduleProxyFactory.deployModule( await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); const predictedFreezeVotingAddress = await calculateProxyAddress( moduleProxyFactory, await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); freezeVoting = await hre.ethers.getContractAt( - "ERC20FreezeVoting", - predictedFreezeVotingAddress + 'ERC20FreezeVoting', + predictedFreezeVotingAddress, ); // Deploy FreezeGuard mastercopy contract - freezeGuardMastercopy = await new MultisigFreezeGuard__factory( - deployer - ).deploy(); + freezeGuardMastercopy = await new MultisigFreezeGuard__factory(deployer).deploy(); // Deploy MultisigFreezeGuard contract with a 60 block timelock period, and a 60 block execution period const freezeGuardSetupData = // eslint-disable-next-line camelcase - MultisigFreezeGuard__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["uint32", "uint32", "address", "address", "address"], - [ - 60, // Timelock period - 60, // Execution period - freezeGuardOwner.address, - await freezeVoting.getAddress(), - await gnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeGuard__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['uint32', 'uint32', 'address', 'address', 'address'], + [ + 60, // Timelock period + 60, // Execution period + freezeGuardOwner.address, + await freezeVoting.getAddress(), + await gnosisSafe.getAddress(), + ], + ), + ]); await moduleProxyFactory.deployModule( await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); const predictedFreezeGuardAddress = await calculateProxyAddress( moduleProxyFactory, await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); freezeGuard = await hre.ethers.getContractAt( - "MultisigFreezeGuard", - predictedFreezeGuardAddress + 'MultisigFreezeGuard', + predictedFreezeGuardAddress, ); // Create transaction to set the guard address - const setGuardData = gnosisSafe.interface.encodeFunctionData("setGuard", [ + const setGuardData = gnosisSafe.interface.encodeFunctionData('setGuard', [ await freezeGuard.getAddress(), ]); @@ -256,18 +229,16 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); // Gnosis Safe received the 1,000 tokens - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 1000 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(1000); }); - describe("FreezeGuard Functionality", () => { - it("Freeze parameters correctly setup", async () => { + describe('FreezeGuard Functionality', () => { + it('Freeze parameters correctly setup', async () => { // Frozen Params init correctly expect(await freezeVoting.freezeVotesThreshold()).to.eq(1090); expect(await freezeVoting.freezeProposalPeriod()).to.eq(10); @@ -275,7 +246,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { expect(await freezeVoting.owner()).to.eq(freezeGuardOwner.address); }); - it("Updates state properly due to freeze actions", async () => { + it('Updates state properly due to freeze actions', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); @@ -283,21 +254,19 @@ describe("Child Multisig DAO with Azorius Parent", () => { await freezeVoting.connect(tokenVetoer1).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - const latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + const latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); await freezeVoting.connect(tokenVetoer2).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(true); }); - it("A transaction can be timelocked and executed", async () => { + it('A transaction can be timelocked and executed', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -323,19 +292,16 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); - const latestBlock = await hre.ethers.provider.getBlock("latest"); + const latestBlock = await hre.ethers.provider.getBlock('latest'); - const signaturesHash = ethers.solidityPackedKeccak256( - ["bytes"], - [signatureBytes] - ); + const signaturesHash = ethers.solidityPackedKeccak256(['bytes'], [signatureBytes]); - expect( - await freezeGuard.getTransactionTimelockedBlock(signaturesHash) - ).to.eq(latestBlock!.number); + expect(await freezeGuard.getTransactionTimelockedBlock(signaturesHash)).to.eq( + latestBlock!.number, + ); // Move time forward to elapse timelock period await time.advanceBlocks(60); @@ -350,21 +316,19 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes + signatureBytes, ); - expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq( - 0 - ); + expect(await votesERC20.balanceOf(await gnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(1000); }); it("A transaction cannot be executed if it hasn't yet been timelocked", async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -390,17 +354,17 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "NotTimelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'NotTimelocked'); }); it("A transaction cannot be timelocked if the signatures aren't valid", async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -425,17 +389,17 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce - ) - ).to.be.revertedWith("GS020"); + tx.nonce, + ), + ).to.be.revertedWith('GS020'); }); - it("A transaction cannot be executed if the timelock period has not ended yet", async () => { + it('A transaction cannot be executed if the timelock period has not ended yet', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -461,7 +425,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); await expect( @@ -475,12 +439,12 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "Timelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Timelocked'); }); - it("A DAO may execute txs during a the freeze proposal period if the freeze threshold is not met", async () => { + it('A DAO may execute txs during a the freeze proposal period if the freeze threshold is not met', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting.connect(tokenVetoer1).castFreezeVote(); @@ -488,10 +452,10 @@ describe("Child Multisig DAO with Azorius Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(false); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -517,7 +481,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -534,12 +498,12 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Casting a vote after the freeze voting period resets state", async () => { + it('Casting a vote after the freeze voting period resets state', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); @@ -547,32 +511,28 @@ describe("Child Multisig DAO with Azorius Parent", () => { await freezeVoting.connect(tokenVetoer1).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - let latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + let latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); // Move time forward to elapse freeze proposal period await time.advanceBlocks(10); await freezeVoting.connect(tokenVetoer1).castFreezeVote(); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); expect(await freezeVoting.isFrozen()).to.eq(false); }); - it("A user cannot vote twice to freeze a dao during the same voting period", async () => { + it('A user cannot vote twice to freeze a dao during the same voting period', async () => { await freezeVoting.connect(tokenVetoer1).castFreezeVote(); await expect( - freezeVoting.connect(tokenVetoer1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "AlreadyVoted"); + freezeVoting.connect(tokenVetoer1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'AlreadyVoted'); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); }); - it("An unfrozen DAO may not execute a previously passed transaction", async () => { + it('An unfrozen DAO may not execute a previously passed transaction', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting.connect(tokenVetoer1).castFreezeVote(); // Vetoer 2 casts 600 freeze votes @@ -582,10 +542,10 @@ describe("Child Multisig DAO with Azorius Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(true); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -611,7 +571,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -628,9 +588,9 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Move time forward to elapse freeze period await time.advanceBlocks(140); @@ -648,12 +608,12 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "Expired"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Expired'); }); - it("Unfrozen DAOs may execute txs", async () => { + it('Unfrozen DAOs may execute txs', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting.connect(tokenVetoer1).castFreezeVote(); // Vetoer 2 casts 600 freeze votes @@ -665,10 +625,10 @@ describe("Child Multisig DAO with Azorius Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(false); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -694,7 +654,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -712,98 +672,94 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("You must have voting weight to cast a freeze vote", async () => { + it('You must have voting weight to cast a freeze vote', async () => { await expect( - freezeVoting.connect(freezeGuardOwner).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + freezeVoting.connect(freezeGuardOwner).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); freezeVoting.connect(tokenVetoer1).castFreezeVote(); await expect( - freezeVoting.connect(freezeGuardOwner).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + freezeVoting.connect(freezeGuardOwner).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); }); - it("Only owner methods must be called by vetoGuard owner", async () => { - await expect( - freezeVoting.connect(tokenVetoer1).unfreeze() - ).to.be.revertedWith("Ownable: caller is not the owner"); - await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + it('Only owner methods must be called by vetoGuard owner', async () => { + await expect(freezeVoting.connect(tokenVetoer1).unfreeze()).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezePeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(freezeVoting.connect(tokenVetoer1).updateFreezePeriod(0)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze voting owner can update the freeze votes threshold", async () => { + it('Only the freeze voting owner can update the freeze votes threshold', async () => { expect(await freezeVoting.freezeVotesThreshold()).to.eq(1090); - await freezeVoting - .connect(freezeGuardOwner) - .updateFreezeVotesThreshold(2000); + await freezeVoting.connect(freezeGuardOwner).updateFreezeVotesThreshold(2000); expect(await freezeVoting.freezeVotesThreshold()).to.eq(2000); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(3000) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(3000), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Only the freeze voting owner can update the freeze proposal period", async () => { + it('Only the freeze voting owner can update the freeze proposal period', async () => { expect(await freezeVoting.freezeProposalPeriod()).to.eq(10); - await freezeVoting - .connect(freezeGuardOwner) - .updateFreezeProposalPeriod(12); + await freezeVoting.connect(freezeGuardOwner).updateFreezeProposalPeriod(12); expect(await freezeVoting.freezeProposalPeriod()).to.eq(12); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(14) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(14), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Only the freeze voting owner can update the freeze period", async () => { + it('Only the freeze voting owner can update the freeze period', async () => { expect(await freezeVoting.freezePeriod()).to.eq(200); await freezeVoting.connect(freezeGuardOwner).updateFreezePeriod(300); expect(await freezeVoting.freezePeriod()).to.eq(300); - await expect( - freezeVoting.connect(tokenVetoer1).updateFreezePeriod(400) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeVoting.connect(tokenVetoer1).updateFreezePeriod(400)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze guard owner can update the timelock period", async () => { + it('Only the freeze guard owner can update the timelock period', async () => { expect(await freezeGuard.timelockPeriod()).to.eq(60); await freezeGuard.connect(freezeGuardOwner).updateTimelockPeriod(70); expect(await freezeGuard.timelockPeriod()).to.eq(70); - await expect( - freezeGuard.connect(tokenVetoer1).updateTimelockPeriod(80) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeGuard.connect(tokenVetoer1).updateTimelockPeriod(80)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze guard owner can update the execution period", async () => { + it('Only the freeze guard owner can update the execution period', async () => { expect(await freezeGuard.executionPeriod()).to.eq(60); await freezeGuard.connect(freezeGuardOwner).updateExecutionPeriod(80); expect(await freezeGuard.executionPeriod()).to.eq(80); - await expect( - freezeGuard.connect(tokenVetoer1).updateExecutionPeriod(90) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeGuard.connect(tokenVetoer1).updateExecutionPeriod(90)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); }); diff --git a/test/MultisigFreezeGuard-ERC721FreezeVoting.test.ts b/test/MultisigFreezeGuard-ERC721FreezeVoting.test.ts index 4263c337..6fc5ccb3 100644 --- a/test/MultisigFreezeGuard-ERC721FreezeVoting.test.ts +++ b/test/MultisigFreezeGuard-ERC721FreezeVoting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { ERC721FreezeVoting, ERC721FreezeVoting__factory, @@ -17,21 +15,22 @@ import { Azorius, GnosisSafeL2__factory, GnosisSafeL2, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; +import time from './time'; -describe("Child Multisig DAO with Azorius Parent", () => { +describe('Child Multisig DAO with Azorius Parent', () => { // Deployed contracts let gnosisSafe: GnosisSafeL2; let freezeGuardMastercopy: MultisigFreezeGuard; @@ -60,27 +59,15 @@ describe("Child Multisig DAO with Azorius Parent", () => { let createGnosisSetupCalldata: string; const threshold = 2; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); - - async function mintNFT( - contract: MockERC721, - receiver: SignerWithAddress - ): Promise { + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); + + async function mintNFT(contract: MockERC721, receiver: SignerWithAddress): Promise { await contract.connect(receiver).mint(receiver.address); } beforeEach(async () => { - [ - deployer, - owner1, - owner2, - owner3, - tokenVetoer1, - tokenVetoer2, - freezeGuardOwner, - ] = await hre.ethers.getSigners(); + [deployer, owner1, owner2, owner3, tokenVetoer1, tokenVetoer2, freezeGuardOwner] = + await hre.ethers.getSigners(); const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); const moduleProxyFactory = getModuleProxyFactory(); @@ -88,7 +75,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { createGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ [owner1.address, owner2.address, owner3.address], threshold, ethers.ZeroAddress, @@ -103,22 +90,19 @@ describe("Child Multisig DAO with Azorius Parent", () => { createGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createGnosisSetupCalldata, - saltNum + saltNum, ); // Get Gnosis Safe contract // eslint-disable-next-line camelcase - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); + gnosisSafe = GnosisSafeL2__factory.connect(predictedGnosisSafeAddress, deployer); const abiCoder = new ethers.AbiCoder(); // encode data @@ -132,18 +116,16 @@ describe("Child Multisig DAO with Azorius Parent", () => { vetoer1Ids = [0]; vetoer2Ids = [1, 2]; - mintNFTData = mockNFT.interface.encodeFunctionData("mint", [ - deployer.address, - ]); + mintNFTData = mockNFT.interface.encodeFunctionData('mint', [deployer.address]); // Deploy Azorius module azoriusMastercopy = await new Azorius__factory(deployer).deploy(); const azoriusSetupCalldata = // eslint-disable-next-line camelcase - Azorius__factory.createInterface().encodeFunctionData("setUp", [ + Azorius__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "address", "address", "address[]", "uint32", "uint32"], + ['address', 'address', 'address', 'address[]', 'uint32', 'uint32'], [ owner1.address, await gnosisSafe.getAddress(), @@ -151,164 +133,149 @@ describe("Child Multisig DAO with Azorius Parent", () => { [], 60, // timelock period in blocks 60, // execution period in blocks - ] + ], ), ]); await moduleProxyFactory.deployModule( await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); const predictedAzoriusAddress = await calculateProxyAddress( moduleProxyFactory, await azoriusMastercopy.getAddress(), azoriusSetupCalldata, - "10031021" + '10031021', ); - azorius = await hre.ethers.getContractAt( - "Azorius", - predictedAzoriusAddress - ); + azorius = await hre.ethers.getContractAt('Azorius', predictedAzoriusAddress); // Deploy Linear ERC721 Voting Mastercopy - linearERC721VotingMastercopy = await new LinearERC721Voting__factory( - deployer - ).deploy(); + linearERC721VotingMastercopy = await new LinearERC721Voting__factory(deployer).deploy(); const linearERC721VotingSetupCalldata = // eslint-disable-next-line camelcase - LinearERC721Voting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - [ - "address", - "address[]", - "uint256[]", - "address", - "uint32", - "uint256", - "uint256", - "uint256", - ], - [ - owner1.address, // owner - [await mockNFT.getAddress()], // NFT addresses - [500], // NFT weights - await azorius.getAddress(), // Azorius module - 60, // voting period in blocks - 2, // quorom threshold - 2, // proposer threshold - 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) - ] - ), - ] - ); + LinearERC721Voting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + [ + 'address', + 'address[]', + 'uint256[]', + 'address', + 'uint32', + 'uint256', + 'uint256', + 'uint256', + ], + [ + owner1.address, // owner + [await mockNFT.getAddress()], // NFT addresses + [500], // NFT weights + await azorius.getAddress(), // Azorius module + 60, // voting period in blocks + 2, // quorom threshold + 2, // proposer threshold + 500000, // basis numerator, denominator is 1,000,000, so basis percentage is 50% (simple majority) + ], + ), + ]); await moduleProxyFactory.deployModule( await linearERC721VotingMastercopy.getAddress(), linearERC721VotingSetupCalldata, - "10031021" + '10031021', ); const predictedlinearERC721VotingAddress = await calculateProxyAddress( moduleProxyFactory, await linearERC721VotingMastercopy.getAddress(), linearERC721VotingSetupCalldata, - "10031021" + '10031021', ); linearERC721Voting = await hre.ethers.getContractAt( - "LinearERC721Voting", - predictedlinearERC721VotingAddress + 'LinearERC721Voting', + predictedlinearERC721VotingAddress, ); // Deploy ERC721FreezeVoting mastercopy contract - freezeVotingMastercopy = await new ERC721FreezeVoting__factory( - deployer - ).deploy(); + freezeVotingMastercopy = await new ERC721FreezeVoting__factory(deployer).deploy(); // Initialize FreezeVoting contract const freezeVotingSetupData = // eslint-disable-next-line camelcase - ERC20FreezeVoting__factory.createInterface().encodeFunctionData("setUp", [ + ERC20FreezeVoting__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["address", "uint256", "uint32", "uint32", "address"], + ['address', 'uint256', 'uint32', 'uint32', 'address'], [ freezeGuardOwner.address, 501, // freeze votes threshold 10, // freeze proposal period 200, // freeze period await linearERC721Voting.getAddress(), // strategy address - ] + ], ), ]); await moduleProxyFactory.deployModule( await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); const predictedFreezeVotingAddress = await calculateProxyAddress( moduleProxyFactory, await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); freezeVoting = await hre.ethers.getContractAt( - "ERC721FreezeVoting", - predictedFreezeVotingAddress + 'ERC721FreezeVoting', + predictedFreezeVotingAddress, ); // Deploy FreezeGuard mastercopy contract - freezeGuardMastercopy = await new MultisigFreezeGuard__factory( - deployer - ).deploy(); + freezeGuardMastercopy = await new MultisigFreezeGuard__factory(deployer).deploy(); // Deploy MultisigFreezeGuard contract with a 60 block timelock period, and a 60 block execution period const freezeGuardSetupData = // eslint-disable-next-line camelcase - MultisigFreezeGuard__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["uint32", "uint32", "address", "address", "address"], - [ - 60, // Timelock period - 60, // Execution period - freezeGuardOwner.address, - await freezeVoting.getAddress(), - await gnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeGuard__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['uint32', 'uint32', 'address', 'address', 'address'], + [ + 60, // Timelock period + 60, // Execution period + freezeGuardOwner.address, + await freezeVoting.getAddress(), + await gnosisSafe.getAddress(), + ], + ), + ]); await moduleProxyFactory.deployModule( await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); const predictedFreezeGuardAddress = await calculateProxyAddress( moduleProxyFactory, await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); freezeGuard = await hre.ethers.getContractAt( - "MultisigFreezeGuard", - predictedFreezeGuardAddress + 'MultisigFreezeGuard', + predictedFreezeGuardAddress, ); // Create transaction to set the guard address - const setGuardData = gnosisSafe.interface.encodeFunctionData("setGuard", [ + const setGuardData = gnosisSafe.interface.encodeFunctionData('setGuard', [ await freezeGuard.getAddress(), ]); @@ -336,13 +303,13 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - describe("FreezeGuard Functionality", () => { - it("Freeze parameters correctly setup", async () => { + describe('FreezeGuard Functionality', () => { + it('Freeze parameters correctly setup', async () => { // Frozen Params init correctly expect(await freezeVoting.freezeVotesThreshold()).to.eq(501); expect(await freezeVoting.freezeProposalPeriod()).to.eq(10); @@ -350,34 +317,28 @@ describe("Child Multisig DAO with Azorius Parent", () => { expect(await freezeVoting.owner()).to.eq(freezeGuardOwner.address); }); - it("Updates state properly due to freeze actions", async () => { + it('Updates state properly due to freeze actions', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); // Vetoer 1 casts 500 freeze votes await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - const latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + const latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); await freezeVoting .connect(tokenVetoer2) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress(), await mockNFT.getAddress()], - vetoer2Ids - ); + [ + 'castFreezeVote(address[],uint256[])' + ]([await mockNFT.getAddress(), await mockNFT.getAddress()], vetoer2Ids); expect(await freezeVoting.isFrozen()).to.eq(true); }); - it("A transaction can be timelocked and executed", async () => { + it('A transaction can be timelocked and executed', async () => { const tx = buildSafeTransaction({ to: await mockNFT.getAddress(), data: mintNFTData, @@ -402,19 +363,16 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); - const latestBlock = await hre.ethers.provider.getBlock("latest"); + const latestBlock = await hre.ethers.provider.getBlock('latest'); - const signaturesHash = ethers.solidityPackedKeccak256( - ["bytes"], - [signatureBytes] - ); + const signaturesHash = ethers.solidityPackedKeccak256(['bytes'], [signatureBytes]); - expect( - await freezeGuard.getTransactionTimelockedBlock(signaturesHash) - ).to.eq(latestBlock!.number); + expect(await freezeGuard.getTransactionTimelockedBlock(signaturesHash)).to.eq( + latestBlock!.number, + ); // Move time forward to elapse timelock period await time.advanceBlocks(60); @@ -429,7 +387,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes + signatureBytes, ); expect(await mockNFT.balanceOf(deployer.address)).to.eq(1); @@ -460,9 +418,9 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "NotTimelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'NotTimelocked'); }); it("A transaction cannot be timelocked if the signatures aren't valid", async () => { @@ -489,12 +447,12 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce - ) - ).to.be.revertedWith("GS020"); + tx.nonce, + ), + ).to.be.revertedWith('GS020'); }); - it("A transaction cannot be executed if the timelock period has not ended yet", async () => { + it('A transaction cannot be executed if the timelock period has not ended yet', async () => { const tx = buildSafeTransaction({ to: await mockNFT.getAddress(), data: mintNFTData, @@ -519,7 +477,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); await expect( @@ -533,19 +491,16 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "Timelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Timelocked'); }); - it("A DAO may execute txs during a the freeze proposal period if the freeze threshold is not met", async () => { + it('A DAO may execute txs during a the freeze proposal period if the freeze threshold is not met', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); // Check that the DAO has been frozen expect(await freezeVoting.isFrozen()).to.eq(false); @@ -574,7 +529,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -591,79 +546,59 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("Casting a vote after the freeze voting period resets state", async () => { + it('Casting a vote after the freeze voting period resets state', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); // Vetoer 1 casts 500 freeze votes await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - let latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + let latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); // Move time forward to elapse freeze proposal period await time.advanceBlocks(10); await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); - latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); expect(await freezeVoting.isFrozen()).to.eq(false); }); - it("A user cannot vote twice to freeze a dao during the same voting period", async () => { + it('A user cannot vote twice to freeze a dao during the same voting period', async () => { await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); await expect( freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ) - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(500); }); - it("An unfrozen DAO may not execute a previously passed transaction", async () => { + it('An unfrozen DAO may not execute a previously passed transaction', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); // Vetoer 2 casts 1000 freeze votes await freezeVoting .connect(tokenVetoer2) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress(), await mockNFT.getAddress()], - vetoer2Ids - ); + [ + 'castFreezeVote(address[],uint256[])' + ]([await mockNFT.getAddress(), await mockNFT.getAddress()], vetoer2Ids); // Check that the DAO has been frozen expect(await freezeVoting.isFrozen()).to.eq(true); @@ -692,7 +627,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -709,9 +644,9 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Move time forward to elapse freeze period await time.advanceBlocks(140); @@ -729,26 +664,22 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "Expired"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Expired'); }); - it("Unfrozen DAOs may execute txs", async () => { + it('Unfrozen DAOs may execute txs', async () => { // Vetoer 1 casts 500 freeze votes await freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); // Vetoer 2 casts 1000 freeze votes await freezeVoting .connect(tokenVetoer2) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress(), await mockNFT.getAddress()], - vetoer2Ids - ); + [ + 'castFreezeVote(address[],uint256[])' + ]([await mockNFT.getAddress(), await mockNFT.getAddress()], vetoer2Ids); // Check that the DAO has been frozen expect(await freezeVoting.isFrozen()).to.eq(true); @@ -779,7 +710,7 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -797,113 +728,102 @@ describe("Child Multisig DAO with Azorius Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(gnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(gnosisSafe, 'ExecutionSuccess'); }); - it("You must have voting weight to cast a freeze vote", async () => { + it('You must have voting weight to cast a freeze vote', async () => { await expect( freezeVoting .connect(freezeGuardOwner) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ) - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); freezeVoting .connect(tokenVetoer1) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress()], - vetoer1Ids - ); + ['castFreezeVote(address[],uint256[])']([await mockNFT.getAddress()], vetoer1Ids); await expect( freezeVoting .connect(freezeGuardOwner) - ["castFreezeVote(address[],uint256[])"]( - [await mockNFT.getAddress(), await mockNFT.getAddress()], - vetoer2Ids - ) - ).to.be.revertedWithCustomError(freezeVoting, "NoVotes()"); + [ + 'castFreezeVote(address[],uint256[])' + ]([await mockNFT.getAddress(), await mockNFT.getAddress()], vetoer2Ids), + ).to.be.revertedWithCustomError(freezeVoting, 'NoVotes()'); }); - it("Only owner methods must be called by vetoGuard owner", async () => { - await expect( - freezeVoting.connect(tokenVetoer1).unfreeze() - ).to.be.revertedWith("Ownable: caller is not the owner"); - await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + it('Only owner methods must be called by vetoGuard owner', async () => { + await expect(freezeVoting.connect(tokenVetoer1).unfreeze()).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezePeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); + await expect(freezeVoting.connect(tokenVetoer1).updateFreezePeriod(0)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze voting owner can update the freeze votes threshold", async () => { + it('Only the freeze voting owner can update the freeze votes threshold', async () => { expect(await freezeVoting.freezeVotesThreshold()).to.eq(501); - await freezeVoting - .connect(freezeGuardOwner) - .updateFreezeVotesThreshold(2000); + await freezeVoting.connect(freezeGuardOwner).updateFreezeVotesThreshold(2000); expect(await freezeVoting.freezeVotesThreshold()).to.eq(2000); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(3000) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeVotesThreshold(3000), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Only the freeze voting owner can update the freeze proposal period", async () => { + it('Only the freeze voting owner can update the freeze proposal period', async () => { expect(await freezeVoting.freezeProposalPeriod()).to.eq(10); - await freezeVoting - .connect(freezeGuardOwner) - .updateFreezeProposalPeriod(12); + await freezeVoting.connect(freezeGuardOwner).updateFreezeProposalPeriod(12); expect(await freezeVoting.freezeProposalPeriod()).to.eq(12); await expect( - freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(14) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(tokenVetoer1).updateFreezeProposalPeriod(14), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); - it("Only the freeze voting owner can update the freeze period", async () => { + it('Only the freeze voting owner can update the freeze period', async () => { expect(await freezeVoting.freezePeriod()).to.eq(200); await freezeVoting.connect(freezeGuardOwner).updateFreezePeriod(300); expect(await freezeVoting.freezePeriod()).to.eq(300); - await expect( - freezeVoting.connect(tokenVetoer1).updateFreezePeriod(400) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeVoting.connect(tokenVetoer1).updateFreezePeriod(400)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze guard owner can update the timelock period", async () => { + it('Only the freeze guard owner can update the timelock period', async () => { expect(await freezeGuard.timelockPeriod()).to.eq(60); await freezeGuard.connect(freezeGuardOwner).updateTimelockPeriod(70); expect(await freezeGuard.timelockPeriod()).to.eq(70); - await expect( - freezeGuard.connect(tokenVetoer1).updateTimelockPeriod(80) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeGuard.connect(tokenVetoer1).updateTimelockPeriod(80)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); - it("Only the freeze guard owner can update the execution period", async () => { + it('Only the freeze guard owner can update the execution period', async () => { expect(await freezeGuard.executionPeriod()).to.eq(60); await freezeGuard.connect(freezeGuardOwner).updateExecutionPeriod(80); expect(await freezeGuard.executionPeriod()).to.eq(80); - await expect( - freezeGuard.connect(tokenVetoer1).updateExecutionPeriod(90) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(freezeGuard.connect(tokenVetoer1).updateExecutionPeriod(90)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); }); }); }); diff --git a/test/MultisigFreezeGuard-MultisigFreezeVoting.test.ts b/test/MultisigFreezeGuard-MultisigFreezeVoting.test.ts index ba487c1e..015fc07f 100644 --- a/test/MultisigFreezeGuard-MultisigFreezeVoting.test.ts +++ b/test/MultisigFreezeGuard-MultisigFreezeVoting.test.ts @@ -1,8 +1,6 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { expect } from "chai"; -import hre from "hardhat"; -import { ethers } from "ethers"; -import time from "./time"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; import { VotesERC20, @@ -13,23 +11,23 @@ import { MultisigFreezeGuard__factory, GnosisSafeL2__factory, GnosisSafeL2, -} from "../typechain-types"; +} from '../typechain-types'; +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, + getModuleProxyFactory, +} from './GlobalSafeDeployments.test'; import { buildSignatureBytes, buildSafeTransaction, safeSignTypedData, predictGnosisSafeAddress, calculateProxyAddress, -} from "./helpers"; - -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, - getModuleProxyFactory, -} from "./GlobalSafeDeployments.test"; +} from './helpers'; +import time from './time'; -describe("Child Multisig DAO with Multisig Parent", () => { +describe('Child Multisig DAO with Multisig Parent', () => { // Deployed contracts let childGnosisSafe: GnosisSafeL2; let freezeGuard: MultisigFreezeGuard; @@ -53,9 +51,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { let createChildGnosisSetupCalldata: string; const threshold = 2; - const saltNum = BigInt( - "0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c" - ); + const saltNum = BigInt('0x856d90216588f9ffc124d1480a440e1c012c7a816952bc968d737bae5d4e139c'); beforeEach(async () => { [ @@ -75,12 +71,8 @@ describe("Child Multisig DAO with Multisig Parent", () => { createParentGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [ - parentMultisigOwner1.address, - parentMultisigOwner2.address, - parentMultisigOwner3.address, - ], + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ + [parentMultisigOwner1.address, parentMultisigOwner2.address, parentMultisigOwner3.address], threshold, ethers.ZeroAddress, ethers.ZeroHash, @@ -92,12 +84,8 @@ describe("Child Multisig DAO with Multisig Parent", () => { createChildGnosisSetupCalldata = // eslint-disable-next-line camelcase - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [ - childMultisigOwner1.address, - childMultisigOwner2.address, - childMultisigOwner3.address, - ], + GnosisSafeL2__factory.createInterface().encodeFunctionData('setup', [ + [childMultisigOwner1.address, childMultisigOwner2.address, childMultisigOwner3.address], threshold, ethers.ZeroAddress, ethers.ZeroHash, @@ -111,43 +99,40 @@ describe("Child Multisig DAO with Multisig Parent", () => { createParentGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); const predictedChildGnosisSafeAddress = await predictGnosisSafeAddress( createChildGnosisSetupCalldata, saltNum, await gnosisSafeL2Singleton.getAddress(), - gnosisSafeProxyFactory + gnosisSafeProxyFactory, ); // Deploy Parent Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createParentGnosisSetupCalldata, - saltNum + saltNum, ); // Deploy Child Gnosis Safe await gnosisSafeProxyFactory.createProxyWithNonce( await gnosisSafeL2Singleton.getAddress(), createChildGnosisSetupCalldata, - saltNum + saltNum, ); // Get Parent Gnosis Safe contract // eslint-disable-next-line camelcase const parentGnosisSafe = GnosisSafeL2__factory.connect( predictedParentGnosisSafeAddress, - deployer + deployer, ); // Get Child Gnosis Safe contract // eslint-disable-next-line camelcase - childGnosisSafe = GnosisSafeL2__factory.connect( - predictedChildGnosisSafeAddress, - deployer - ); + childGnosisSafe = GnosisSafeL2__factory.connect(predictedChildGnosisSafeAddress, deployer); // Deploy token mastercopy votesERC20Mastercopy = await new VotesERC20__factory(deployer).deploy(); @@ -155,119 +140,105 @@ describe("Child Multisig DAO with Multisig Parent", () => { const abiCoder = new ethers.AbiCoder(); // encode data const votesERC20SetupData = // eslint-disable-next-line camelcase - VotesERC20__factory.createInterface().encodeFunctionData("setUp", [ + VotesERC20__factory.createInterface().encodeFunctionData('setUp', [ abiCoder.encode( - ["string", "string", "address[]", "uint256[]"], - ["DCNT", "DCNT", [await childGnosisSafe.getAddress()], [1000]] + ['string', 'string', 'address[]', 'uint256[]'], + ['DCNT', 'DCNT', [await childGnosisSafe.getAddress()], [1000]], ), ]); await moduleProxyFactory.deployModule( await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); const predictedVotesERC20Address = await calculateProxyAddress( moduleProxyFactory, await votesERC20Mastercopy.getAddress(), votesERC20SetupData, - "10031021" + '10031021', ); - votesERC20 = await hre.ethers.getContractAt( - "VotesERC20", - predictedVotesERC20Address - ); + votesERC20 = await hre.ethers.getContractAt('VotesERC20', predictedVotesERC20Address); // Deploy MultisigFreezeVoting mastercopy contract - freezeVotingMastercopy = await new MultisigFreezeVoting__factory( - deployer - ).deploy(); + freezeVotingMastercopy = await new MultisigFreezeVoting__factory(deployer).deploy(); // Initialize MultisigFreezeVoting contract const freezeVotingSetupData = // eslint-disable-next-line camelcase - MultisigFreezeVoting__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["address", "uint256", "uint32", "uint32", "address"], - [ - freezeGuardOwner.address, - 2, // freeze votes threshold - 10, // freeze proposal duration in blocks - 200, // freeze duration in blocks - await parentGnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeVoting__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['address', 'uint256', 'uint32', 'uint32', 'address'], + [ + freezeGuardOwner.address, + 2, // freeze votes threshold + 10, // freeze proposal duration in blocks + 200, // freeze duration in blocks + await parentGnosisSafe.getAddress(), + ], + ), + ]); await moduleProxyFactory.deployModule( await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); const predictedFreezeVotingAddress = await calculateProxyAddress( moduleProxyFactory, await freezeVotingMastercopy.getAddress(), freezeVotingSetupData, - "10031021" + '10031021', ); freezeVoting = await hre.ethers.getContractAt( - "MultisigFreezeVoting", - predictedFreezeVotingAddress + 'MultisigFreezeVoting', + predictedFreezeVotingAddress, ); // Deploy FreezeGuard mastercopy contract - const freezeGuardMastercopy = await new MultisigFreezeGuard__factory( - deployer - ).deploy(); + const freezeGuardMastercopy = await new MultisigFreezeGuard__factory(deployer).deploy(); // Deploy MultisigFreezeGuard contract with a 60 block timelock period and 60 block execution period const freezeGuardSetupData = // eslint-disable-next-line camelcase - MultisigFreezeGuard__factory.createInterface().encodeFunctionData( - "setUp", - [ - abiCoder.encode( - ["uint32", "uint32", "address", "address", "address"], - [ - 60, // Timelock period - 60, // Execution period - freezeGuardOwner.address, - await freezeVoting.getAddress(), - await childGnosisSafe.getAddress(), - ] - ), - ] - ); + MultisigFreezeGuard__factory.createInterface().encodeFunctionData('setUp', [ + abiCoder.encode( + ['uint32', 'uint32', 'address', 'address', 'address'], + [ + 60, // Timelock period + 60, // Execution period + freezeGuardOwner.address, + await freezeVoting.getAddress(), + await childGnosisSafe.getAddress(), + ], + ), + ]); await moduleProxyFactory.deployModule( await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); const predictedFreezeGuardAddress = await calculateProxyAddress( moduleProxyFactory, await freezeGuardMastercopy.getAddress(), freezeGuardSetupData, - "10031021" + '10031021', ); freezeGuard = await hre.ethers.getContractAt( - "MultisigFreezeGuard", - predictedFreezeGuardAddress + 'MultisigFreezeGuard', + predictedFreezeGuardAddress, ); // Create transaction to set the guard address - const setGuardData = childGnosisSafe.interface.encodeFunctionData( - "setGuard", - [await freezeGuard.getAddress()] - ); + const setGuardData = childGnosisSafe.interface.encodeFunctionData('setGuard', [ + await freezeGuard.getAddress(), + ]); const tx = buildSafeTransaction({ to: await childGnosisSafe.getAddress(), @@ -293,18 +264,16 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.emit(childGnosisSafe, "ExecutionSuccess"); + signatureBytes, + ), + ).to.emit(childGnosisSafe, 'ExecutionSuccess'); // Gnosis Safe received the 1,000 tokens - expect( - await votesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(1000); + expect(await votesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(1000); }); - describe("MultisigFreezeGuard with MultisigFreezeVoting", () => { - it("Freeze vars set properly during init", async () => { + describe('MultisigFreezeGuard with MultisigFreezeVoting', () => { + it('Freeze vars set properly during init', async () => { // Frozen Params init correctly expect(await freezeVoting.freezeVotesThreshold()).to.eq(2); expect(await freezeVoting.freezeProposalPeriod()).to.eq(10); @@ -312,7 +281,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { expect(await freezeVoting.owner()).to.eq(freezeGuardOwner.address); }); - it("Updates state properly due to freeze actions", async () => { + it('Updates state properly due to freeze actions', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); @@ -320,21 +289,19 @@ describe("Child Multisig DAO with Multisig Parent", () => { await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); - const latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + const latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); await freezeVoting.connect(parentMultisigOwner2).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(true); }); - it("A transaction can be timelocked and executed", async () => { + it('A transaction can be timelocked and executed', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -360,7 +327,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); // Move time forward to elapse timelock period @@ -376,21 +343,19 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes + signatureBytes, ); - expect( - await votesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(0); + expect(await votesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(1000); }); - it("The same transaction must be timelocked separately if being executed more than once", async () => { + it('The same transaction must be timelocked separately if being executed more than once', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -416,7 +381,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); // Move time forward to elapse timelock period @@ -432,12 +397,10 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes + signatureBytes, ); - expect( - await votesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(0); + expect(await votesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(1000); await expect( @@ -451,17 +414,17 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWith("GS026"); + signatureBytes, + ), + ).to.be.revertedWith('GS026'); }); - it("The same transaction can be executed twice if it is timelocked separately", async () => { + it('The same transaction can be executed twice if it is timelocked separately', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 500] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 500, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -500,7 +463,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); await freezeGuard.timelockTransaction( @@ -514,7 +477,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasToken, tx2.refundReceiver, signatureBytes2, - tx2.nonce + tx2.nonce, ); // Move time forward to elapse timelock period @@ -531,7 +494,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 + signatureBytes1, ); // Execute the second transaction @@ -545,21 +508,19 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasPrice, tx2.gasToken, tx2.refundReceiver, - signatureBytes2 + signatureBytes2, ); - expect( - await votesERC20.balanceOf(await childGnosisSafe.getAddress()) - ).to.eq(0); + expect(await votesERC20.balanceOf(await childGnosisSafe.getAddress())).to.eq(0); expect(await votesERC20.balanceOf(deployer.address)).to.eq(1000); }); it("A transaction cannot be executed if it hasn't yet been timelocked", async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -585,17 +546,17 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "NotTimelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'NotTimelocked'); }); it("A transaction cannot be timelocked if the signatures aren't valid", async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -605,9 +566,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { }); // Only 1 signer signs, while the threshold is 2 - const sigs = [ - await safeSignTypedData(childMultisigOwner1, childGnosisSafe, tx), - ]; + const sigs = [await safeSignTypedData(childMultisigOwner1, childGnosisSafe, tx)]; const signatureBytes = buildSignatureBytes(sigs); await expect( @@ -622,17 +581,17 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce - ) - ).to.be.revertedWith("GS020"); + tx.nonce, + ), + ).to.be.revertedWith('GS020'); }); - it("A transaction cannot be executed if the timelock period has not ended yet", async () => { + it('A transaction cannot be executed if the timelock period has not ended yet', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -658,7 +617,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); await expect( @@ -672,22 +631,22 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasPrice, tx.gasToken, tx.refundReceiver, - signatureBytes - ) - ).to.be.revertedWithCustomError(freezeGuard, "Timelocked"); + signatureBytes, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Timelocked'); }); - it("A frozen DAO cannot execute any transactions", async () => { + it('A frozen DAO cannot execute any transactions', async () => { // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); - const tokenTransferData2 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 999] - ); + const tokenTransferData2 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 999, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -726,7 +685,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Vetoer 1 casts 1 freeze vote @@ -755,9 +714,9 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Timelock tx2 await freezeGuard.timelockTransaction( @@ -771,7 +730,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasToken, tx2.refundReceiver, signatureBytes2, - tx2.nonce + tx2.nonce, ); // Move time forward to elapse timelock period @@ -788,22 +747,22 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasPrice, tx2.gasToken, tx2.refundReceiver, - signatureBytes2 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes2, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); }); - it("A frozen DAO automatically unfreezes after the freeze period has ended", async () => { + it('A frozen DAO automatically unfreezes after the freeze period has ended', async () => { // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); - const tokenTransferData2 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 999] - ); + const tokenTransferData2 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 999, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -842,7 +801,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Vetoer 1 casts 1 freeze vote @@ -871,9 +830,9 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Timelock tx2 await freezeGuard.timelockTransaction( @@ -887,7 +846,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasToken, tx2.refundReceiver, signatureBytes2, - tx2.nonce + tx2.nonce, ); // Move time forward to elapse timelock period @@ -904,9 +863,9 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx2.gasPrice, tx2.gasToken, tx2.refundReceiver, - signatureBytes2 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes2, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); expect(await freezeVoting.isFrozen()).to.eq(true); @@ -917,7 +876,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(false); }); - it("A DAO may execute txs during a freeze proposal period if the freeze threshold is not met", async () => { + it('A DAO may execute txs during a freeze proposal period if the freeze threshold is not met', async () => { // Vetoer 1 casts 1 freeze vote await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); @@ -925,10 +884,10 @@ describe("Child Multisig DAO with Multisig Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(false); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -954,7 +913,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -971,12 +930,12 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(childGnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(childGnosisSafe, 'ExecutionSuccess'); }); - it("Casting a vote after the freeze voting period resets state", async () => { + it('Casting a vote after the freeze voting period resets state', async () => { expect(await freezeVoting.freezeProposalVoteCount()).to.eq(0); expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(0); @@ -984,32 +943,28 @@ describe("Child Multisig DAO with Multisig Parent", () => { await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); expect(await freezeVoting.isFrozen()).to.eq(false); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); - let latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + let latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); // Move time forward to elapse freeze proposal period await time.advanceBlocks(20); await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); - latestBlock = await hre.ethers.provider.getBlock("latest"); - expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq( - latestBlock!.number - ); + latestBlock = await hre.ethers.provider.getBlock('latest'); + expect(await freezeVoting.freezeProposalCreatedBlock()).to.eq(latestBlock!.number); expect(await freezeVoting.isFrozen()).to.eq(false); }); - it("A user cannot vote twice to freeze a DAO during the same voting period", async () => { + it('A user cannot vote twice to freeze a DAO during the same voting period', async () => { await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); await expect( - freezeVoting.connect(parentMultisigOwner1).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "AlreadyVoted"); + freezeVoting.connect(parentMultisigOwner1).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'AlreadyVoted'); expect(await freezeVoting.freezeProposalVoteCount()).to.eq(1); }); - it("Previously Frozen DAOs may not execute TXs after execution period has elapsed", async () => { + it('Previously Frozen DAOs may not execute TXs after execution period has elapsed', async () => { // Vetoer 1 casts 1 freeze vote await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); // Vetoer 2 casts 1 freeze vote @@ -1019,10 +974,10 @@ describe("Child Multisig DAO with Multisig Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(true); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -1048,7 +1003,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -1065,9 +1020,9 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "DAOFrozen()"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'DAOFrozen()'); // Move time forward to elapse freeze period await time.advanceBlocks(140); @@ -1087,12 +1042,12 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.be.revertedWithCustomError(freezeGuard, "Expired"); + signatureBytes1, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'Expired'); }); - it("Unfrozen DAOs may execute txs", async () => { + it('Unfrozen DAOs may execute txs', async () => { // Vetoer 1 casts 1 freeze vote await freezeVoting.connect(parentMultisigOwner1).castFreezeVote(); // Vetoer 2 casts 1 freeze vote @@ -1104,10 +1059,10 @@ describe("Child Multisig DAO with Multisig Parent", () => { expect(await freezeVoting.isFrozen()).to.eq(false); // Create transaction to set the guard address - const tokenTransferData1 = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData1 = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx1 = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -1133,7 +1088,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasToken, tx1.refundReceiver, signatureBytes1, - tx1.nonce + tx1.nonce, ); // Move time forward to elapse timelock period @@ -1151,17 +1106,17 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx1.gasPrice, tx1.gasToken, tx1.refundReceiver, - signatureBytes1 - ) - ).to.emit(childGnosisSafe, "ExecutionSuccess"); + signatureBytes1, + ), + ).to.emit(childGnosisSafe, 'ExecutionSuccess'); }); - it("A transaction cannot be timelocked twice", async () => { + it('A transaction cannot be timelocked twice', async () => { // Create transaction to set the guard address - const tokenTransferData = votesERC20.interface.encodeFunctionData( - "transfer", - [deployer.address, 1000] - ); + const tokenTransferData = votesERC20.interface.encodeFunctionData('transfer', [ + deployer.address, + 1000, + ]); const tx = buildSafeTransaction({ to: await votesERC20.getAddress(), @@ -1187,7 +1142,7 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce + tx.nonce, ); await expect( @@ -1202,30 +1157,30 @@ describe("Child Multisig DAO with Multisig Parent", () => { tx.gasToken, tx.refundReceiver, signatureBytes, - tx.nonce - ) - ).to.be.revertedWithCustomError(freezeGuard, "AlreadyTimelocked"); + tx.nonce, + ), + ).to.be.revertedWithCustomError(freezeGuard, 'AlreadyTimelocked'); }); - it("You must be a parent multisig owner to cast a freeze vote", async () => { + it('You must be a parent multisig owner to cast a freeze vote', async () => { await expect( - freezeVoting.connect(freezeGuardOwner).castFreezeVote() - ).to.be.revertedWithCustomError(freezeVoting, "NotOwner"); + freezeVoting.connect(freezeGuardOwner).castFreezeVote(), + ).to.be.revertedWithCustomError(freezeVoting, 'NotOwner'); }); - it("Only owner methods must be called by the owner", async () => { - await expect( - freezeVoting.connect(childMultisigOwner1).unfreeze() - ).to.be.revertedWith("Ownable: caller is not the owner"); + it('Only owner methods must be called by the owner', async () => { + await expect(freezeVoting.connect(childMultisigOwner1).unfreeze()).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); await expect( - freezeVoting.connect(childMultisigOwner1).updateFreezeVotesThreshold(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(childMultisigOwner1).updateFreezeVotesThreshold(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); await expect( - freezeVoting.connect(childMultisigOwner1).updateFreezeProposalPeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(childMultisigOwner1).updateFreezeProposalPeriod(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); await expect( - freezeVoting.connect(childMultisigOwner1).updateFreezePeriod(0) - ).to.be.revertedWith("Ownable: caller is not the owner"); + freezeVoting.connect(childMultisigOwner1).updateFreezePeriod(0), + ).to.be.revertedWith('Ownable: caller is not the owner'); }); }); }); diff --git a/test/helpers.ts b/test/helpers.ts index 6c291701..17826296 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -1,4 +1,5 @@ -import { ethers, solidityPackedKeccak256 } from "ethers"; +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import hre, { ethers } from 'hardhat'; import { ERC6551Registry, GnosisSafeL2, @@ -6,10 +7,8 @@ import { IAzorius, MockContract__factory, MockHatsAccount__factory, -} from "../typechain-types"; -import { getMockContract } from "./GlobalSafeDeployments.test"; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import hre from "hardhat"; +} from '../typechain-types'; +import { getMockContract } from './GlobalSafeDeployments.test'; export interface MetaTransaction { to: string; @@ -36,18 +35,18 @@ export const predictGnosisSafeAddress = async ( calldata: string, saltNum: string | bigint, singleton: string, - gnosisFactory: GnosisSafeProxyFactory + gnosisFactory: GnosisSafeProxyFactory, ): Promise => { return ethers.getCreate2Address( await gnosisFactory.getAddress(), ethers.solidityPackedKeccak256( - ["bytes", "uint256"], - [ethers.solidityPackedKeccak256(["bytes"], [calldata]), saltNum] + ['bytes', 'uint256'], + [ethers.solidityPackedKeccak256(['bytes'], [calldata]), saltNum], ), ethers.solidityPackedKeccak256( - ["bytes", "uint256"], - [await gnosisFactory.proxyCreationCode(), singleton] - ) + ['bytes', 'uint256'], + [await gnosisFactory.proxyCreationCode(), singleton], + ), ); }; @@ -55,33 +54,29 @@ export const calculateProxyAddress = async ( factory: ethers.BaseContract, masterCopy: string, initData: string, - saltNonce: string + saltNonce: string, ): Promise => { - const masterCopyAddress = masterCopy.toLowerCase().replace(/^0x/, ""); + const masterCopyAddress = masterCopy.toLowerCase().replace(/^0x/, ''); const byteCode = - "0x602d8060093d393df3363d3d373d3d3d363d73" + + '0x602d8060093d393df3363d3d373d3d3d363d73' + masterCopyAddress + - "5af43d82803e903d91602b57fd5bf3"; + '5af43d82803e903d91602b57fd5bf3'; const salt = ethers.solidityPackedKeccak256( - ["bytes32", "uint256"], - [ethers.solidityPackedKeccak256(["bytes"], [initData]), saltNonce] + ['bytes32', 'uint256'], + [ethers.solidityPackedKeccak256(['bytes'], [initData]), saltNonce], ); - return ethers.getCreate2Address( - await factory.getAddress(), - salt, - ethers.keccak256(byteCode) - ); + return ethers.getCreate2Address(await factory.getAddress(), salt, ethers.keccak256(byteCode)); }; export const safeSignTypedData = async ( signer: ethers.Signer, safe: ethers.BaseContract, - safeTx: SafeTransaction + safeTx: SafeTransaction, ): Promise => { if (!signer.provider) { - throw Error("Provider required to retrieve chainId"); + throw Error('Provider required to retrieve chainId'); } const cid = (await signer.provider.getNetwork()).chainId; const signerAddress = await signer.getAddress(); @@ -92,56 +87,34 @@ export const safeSignTypedData = async ( { // "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)" SafeTx: [ - { type: "address", name: "to" }, - { type: "uint256", name: "value" }, - { type: "bytes", name: "data" }, - { type: "uint8", name: "operation" }, - { type: "uint256", name: "safeTxGas" }, - { type: "uint256", name: "baseGas" }, - { type: "uint256", name: "gasPrice" }, - { type: "address", name: "gasToken" }, - { type: "address", name: "refundReceiver" }, - { type: "uint256", name: "nonce" }, + { type: 'address', name: 'to' }, + { type: 'uint256', name: 'value' }, + { type: 'bytes', name: 'data' }, + { type: 'uint8', name: 'operation' }, + { type: 'uint256', name: 'safeTxGas' }, + { type: 'uint256', name: 'baseGas' }, + { type: 'uint256', name: 'gasPrice' }, + { type: 'address', name: 'gasToken' }, + { type: 'address', name: 'refundReceiver' }, + { type: 'uint256', name: 'nonce' }, ], }, - safeTx + safeTx, ), }; }; export const buildSignatureBytes = (signatures: SafeSignature[]): string => { signatures.sort((left, right) => - left.signer.toLowerCase().localeCompare(right.signer.toLowerCase()) + left.signer.toLowerCase().localeCompare(right.signer.toLowerCase()), ); - let signatureBytes = "0x"; + let signatureBytes = '0x'; for (const sig of signatures) { signatureBytes += sig.data.slice(2); } return signatureBytes; }; -export const buildContractCall = async ( - contract: ethers.BaseContract, - method: string, - params: any[], - nonce: number, - delegateCall?: boolean, - overrides?: Partial -): Promise => { - const data = contract.interface.encodeFunctionData(method, params); - return buildSafeTransaction( - Object.assign( - { - to: await contract.getAddress(), - data, - operation: delegateCall ? 1 : 0, - nonce, - }, - overrides - ) - ); -}; - export const buildSafeTransaction = (template: { to: string; value?: bigint | number | string; @@ -157,7 +130,7 @@ export const buildSafeTransaction = (template: { return { to: template.to, value: template.value || 0, - data: template.data || "0x", + data: template.data || '0x', operation: template.operation || 0, safeTxGas: template.safeTxGas || 0, baseGas: template.baseGas || 0, @@ -168,47 +141,63 @@ export const buildSafeTransaction = (template: { }; }; +export const buildContractCall = async ( + contract: ethers.BaseContract, + method: string, + params: any[], + nonce: number, + delegateCall?: boolean, + overrides?: Partial, +): Promise => { + const data = contract.interface.encodeFunctionData(method, params); + return buildSafeTransaction( + Object.assign( + { + to: await contract.getAddress(), + data, + operation: delegateCall ? 1 : 0, + nonce, + }, + overrides, + ), + ); +}; + export const encodeMultiSend = (txs: MetaTransaction[]): string => { return ( - "0x" + + '0x' + txs - .map((tx) => { + .map(tx => { const data = ethers.getBytes(tx.data); const encoded = ethers.solidityPacked( - ["uint8", "address", "uint256", "uint256", "bytes"], - [tx.operation, tx.to, tx.value, data.length, data] + ['uint8', 'address', 'uint256', 'uint256', 'bytes'], + [tx.operation, tx.to, tx.value, data.length, data], ); return encoded.slice(2); }) - .join("") + .join('') ); }; -export const mockTransaction = - async (): Promise => { - return { - to: await getMockContract().getAddress(), - value: 0n, - // eslint-disable-next-line camelcase - data: MockContract__factory.createInterface().encodeFunctionData( - "doSomething" - ), - operation: 0, - }; +export const mockTransaction = async (): Promise => { + return { + to: await getMockContract().getAddress(), + value: 0n, + // eslint-disable-next-line camelcase + data: MockContract__factory.createInterface().encodeFunctionData('doSomething'), + operation: 0, }; +}; -export const mockRevertTransaction = - async (): Promise => { - return { - to: await getMockContract().getAddress(), - value: 0n, - // eslint-disable-next-line camelcase - data: MockContract__factory.createInterface().encodeFunctionData( - "revertSomething" - ), - operation: 0, - }; +export const mockRevertTransaction = async (): Promise => { + return { + to: await getMockContract().getAddress(), + value: 0n, + // eslint-disable-next-line camelcase + data: MockContract__factory.createInterface().encodeFunctionData('revertSomething'), + operation: 0, }; +}; export const executeSafeTransaction = async ({ safe, @@ -228,7 +217,7 @@ export const executeSafeTransaction = async ({ }); const sigs = await Promise.all( - signers.map(async (signer) => await safeSignTypedData(signer, safe, safeTx)) + signers.map(async signer => safeSignTypedData(signer, safe, safeTx)), ); const tx = await safe.execTransaction( @@ -241,7 +230,7 @@ export const executeSafeTransaction = async ({ safeTx.gasPrice, safeTx.gasToken, safeTx.refundReceiver, - buildSignatureBytes(sigs) + buildSignatureBytes(sigs), ); return tx; @@ -252,22 +241,21 @@ export const getHatAccount = async ( erc6551RegistryImplementation: ERC6551Registry, mockHatsAccountImplementationAddress: string, mockHatsAddress: string, - signer?: ethers.Signer + signer?: ethers.Signer, ) => { - const salt = - "0x5d0e6ce4fd951366cc55da93f6e79d8b81483109d79676a04bcc2bed6a4b5072"; + const salt = '0x5d0e6ce4fd951366cc55da93f6e79d8b81483109d79676a04bcc2bed6a4b5072'; const hatAccountAddress = await erc6551RegistryImplementation.account( mockHatsAccountImplementationAddress, salt, await hre.getChainId(), mockHatsAddress, - hatId + hatId, ); const hatAccount = MockHatsAccount__factory.connect( hatAccountAddress, - signer ?? hre.ethers.provider + signer ?? hre.ethers.provider, ); return hatAccount; diff --git a/test/time.ts b/test/time.ts index ca1c63a6..6c520709 100644 --- a/test/time.ts +++ b/test/time.ts @@ -1,4 +1,8 @@ -import hre from "hardhat"; +import hre from 'hardhat'; + +const advanceBlock = async () => { + await hre.ethers.provider.send('evm_mine', []); +}; const advanceBlocks = async (blockCount: number) => { for (let i = 0; i < blockCount; i++) { @@ -6,10 +10,6 @@ const advanceBlocks = async (blockCount: number) => { } }; -const advanceBlock = async () => { - await hre.ethers.provider.send("evm_mine", []); -}; - const defaultExport = { advanceBlocks, advanceBlock, From 3cc64fb0bf410d5b01a1d283ff992f427ce4af20 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Tue, 22 Oct 2024 11:15:28 -0400 Subject: [PATCH 3/3] Add a github action for linting and prettying --- .github/workflows/code-syntax.yml | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/code-syntax.yml diff --git a/.github/workflows/code-syntax.yml b/.github/workflows/code-syntax.yml new file mode 100644 index 00000000..e70a1ced --- /dev/null +++ b/.github/workflows/code-syntax.yml @@ -0,0 +1,37 @@ +name: Code Syntax +on: + push: + branches: + - develop + pull_request: +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + - name: Install dependencies + run: npm ci + - name: Compile contracts + run: npm run compile + - name: Run linter + run: npm run lint:check + pretty: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + - name: Install dependencies + run: npm ci + - name: Compile contracts + run: npm run compile + - name: Run prettier + run: npm run pretty:check