diff --git a/hardhat.config.ts b/hardhat.config.ts index 446cb5e..dbb1747 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,7 +1,6 @@ import 'hardhat-gas-reporter'; import { HardhatUserConfig } from 'hardhat/config'; import '@nomicfoundation/hardhat-toolbox'; -require('@openzeppelin/hardhat-upgrades'); const dotenv = require('dotenv'); dotenv.config({ path: __dirname + '/.env' }); const { COINMARKETCAP_API_KEY } = process.env; diff --git a/on-struct.png b/on-struct.png deleted file mode 100644 index 7980b55..0000000 Binary files a/on-struct.png and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 021b6c8..bd802d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,16 +11,12 @@ "devDependencies": { "@babel/register": "^7.22.5", "@faker-js/faker": "^8.0.2", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@openzeppelin/contracts": "^4.8.3", - "@openzeppelin/contracts-upgradeable": "^4.8.3", - "@openzeppelin/hardhat-upgrades": "^1.25.0", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@openzeppelin/contracts": "^4.9.3", "dotenv": "^16.3.1", "hardhat": "^2.14.0", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.9", - "i": "^0.3.7", - "npm": "^9.8.1", "pino": "^8.15.0", "pino-pretty": "^10.2.0", "prettier": "^2.8.8", @@ -32,6 +28,13 @@ "node": ">=18.10.0" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz", + "integrity": "sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==", + "dev": true, + "peer": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -46,62 +49,6 @@ "node": ">=6.0.0" } }, - "node_modules/@aws-crypto/sha256-js": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz", - "integrity": "sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==", - "dev": true, - "dependencies": { - "@aws-crypto/util": "^1.2.2", - "@aws-sdk/types": "^3.1.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/util": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-1.2.2.tgz", - "integrity": "sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==", - "dev": true, - "dependencies": { - "@aws-sdk/types": "^3.1.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.398.0.tgz", - "integrity": "sha512-r44fkS+vsEgKCuEuTV+TIk0t0m5ZlXHNjSDYEUvzLStbbfUFiNus/YG4UCa0wOk9R7VuQI67badsvvPeVPCGDQ==", - "dev": true, - "dependencies": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -515,6 +462,19 @@ "node": ">=14" } }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", @@ -840,6 +800,12 @@ "scrypt-js": "3.0.1" } }, + "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 + }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", @@ -972,6 +938,27 @@ "ws": "7.4.6" } }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "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" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@ethersproject/random": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", @@ -1357,7 +1344,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/hashes": { + "node_modules/@noble/curves/node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", @@ -1370,6 +1357,19 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@noble/hashes": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", + "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true + }, "node_modules/@noble/secp256k1": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", @@ -1438,6 +1438,54 @@ "node": ">=14" } }, + "node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/@nomicfoundation/ethereumjs-blockchain": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz", @@ -1534,6 +1582,54 @@ "js-sdsl": "^4.1.4" } }, + "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/@nomicfoundation/ethereumjs-trie": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz", @@ -1625,25 +1721,39 @@ } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz", - "integrity": "sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.2.tgz", + "integrity": "sha512-9Wu9mRtkj0U9ohgXYFbB/RQDa+PcEdyBm2suyEtsJf3PqzZEEjLUZgWnMjlFhATMk/fp3BjmnYVPrwl+gr8oEw==", "dev": true, "peer": true, "dependencies": { - "@ethersproject/abi": "^5.1.2", "@types/chai-as-promised": "^7.1.3", "chai-as-promised": "^7.1.1", "deep-eql": "^4.0.1", "ordinal": "^1.0.3" }, "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", "chai": "^4.2.0", - "ethers": "^5.0.0", + "ethers": "^6.1.0", "hardhat": "^2.9.4" } }, + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.4.tgz", + "integrity": "sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" + } + }, "node_modules/@nomicfoundation/hardhat-network-helpers": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz", @@ -1658,32 +1768,51 @@ } }, "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", - "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz", + "integrity": "sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==", "dev": true, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.0.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.2", + "@nomicfoundation/hardhat-verify": "^1.0.0", + "@typechain/ethers-v6": "^0.4.0", + "@typechain/hardhat": "^8.0.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", "@types/node": ">=12.0.0", "chai": "^4.2.0", - "ethers": "^5.4.7", + "ethers": "^6.4.0", "hardhat": "^2.11.0", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.1", "ts-node": ">=8.0.0", - "typechain": "^8.1.0", + "typechain": "^8.2.0", "typescript": ">=4.5.0" } }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-1.1.1.tgz", + "integrity": "sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", @@ -1865,319 +1994,71 @@ "node": ">= 10" } }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz", - "integrity": "sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==", - "dev": true, - "peer": true, - "peerDependencies": { - "ethers": "^5.0.0", - "hardhat": "^2.0.0" - } - }, - "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", - "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", - "dev": true, - "peer": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^8.1.0", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "semver": "^6.3.0", - "table": "^6.8.0", - "undici": "^5.14.0" - }, - "peerDependencies": { - "hardhat": "^2.0.4" - } - }, "node_modules/@openzeppelin/contracts": { "version": "4.9.3", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.3.tgz", "integrity": "sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==", "dev": true }, - "node_modules/@openzeppelin/contracts-upgradeable": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.3.tgz", - "integrity": "sha512-jjaHAVRMrE4UuZNfDwjlLGDxTHWIOwTJS2ldnc278a0gevfXfPr8hxKEVBGFBE96kl2G3VHDZhUimw/+G3TG2A==", - "dev": true - }, - "node_modules/@openzeppelin/defender-base-client": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.48.0.tgz", - "integrity": "sha512-HFO87s010hRrMjyh2xYOCEAkLe21BfIbho7n5/kikA6A1ZgXi7MsEiqnQv1zP4bxMJgxGZ5b3t4tt6fWrakbag==", + "node_modules/@scure/base": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", + "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", "dev": true, - "dependencies": { - "amazon-cognito-identity-js": "^6.0.1", - "async-retry": "^1.3.3", - "axios": "^1.4.0", - "lodash": "^4.17.19", - "node-fetch": "^2.6.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@openzeppelin/hardhat-upgrades": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.28.0.tgz", - "integrity": "sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==", + "node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", "dev": true, + "peer": true, "dependencies": { - "@openzeppelin/defender-base-client": "^1.46.0", - "@openzeppelin/platform-deploy-client": "^0.8.0", - "@openzeppelin/upgrades-core": "^1.27.0", - "chalk": "^4.1.0", - "debug": "^4.1.1", - "proper-lockfile": "^4.1.1" - }, - "bin": { - "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" - }, - "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.1.0", - "ethers": "^5.0.5", - "hardhat": "^2.0.2" - }, - "peerDependenciesMeta": { - "@nomiclabs/harhdat-etherscan": { - "optional": true - } - } - }, - "node_modules/@openzeppelin/hardhat-upgrades/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@openzeppelin/hardhat-upgrades/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@openzeppelin/hardhat-upgrades/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 - }, - "node_modules/@openzeppelin/hardhat-upgrades/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@openzeppelin/hardhat-upgrades/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@openzeppelin/platform-deploy-client": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.8.0.tgz", - "integrity": "sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA==", - "deprecated": "@openzeppelin/platform-deploy-client is deprecated. Please use @openzeppelin/defender-sdk-deploy-client", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.6.3", - "@openzeppelin/defender-base-client": "^1.46.0", - "axios": "^0.21.2", - "lodash": "^4.17.19", - "node-fetch": "^2.6.0" - } - }, - "node_modules/@openzeppelin/platform-deploy-client/node_modules/axios": { - "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" - } - }, - "node_modules/@openzeppelin/upgrades-core": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.28.0.tgz", - "integrity": "sha512-8RKlyg98Adv+46GxDaR0awL3R8bVCcQ27DcSEwrgWOp6siHh8sZg4a2l+2dhPl1510S6uBfhHSydMH5VX2BV5g==", - "dev": true, - "dependencies": { - "cbor": "^9.0.0", - "chalk": "^4.1.0", - "compare-versions": "^6.0.0", - "debug": "^4.1.1", - "ethereumjs-util": "^7.0.3", - "minimist": "^1.2.7", - "proper-lockfile": "^4.1.1", - "solidity-ast": "^0.4.26" - }, - "bin": { - "openzeppelin-upgrades-core": "dist/cli/cli.js" - } - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", - "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==", - "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@openzeppelin/upgrades-core/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 - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "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": ">=8" - } - }, - "node_modules/@openzeppelin/upgrades-core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "node": ">= 16" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@scure/base": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", - "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", - "dev": true, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", "dev": true, "peer": true, "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", + "@noble/hashes": "~1.3.0", "@scure/base": "~1.1.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "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, - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "engines": { + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -2199,6 +2080,12 @@ "node": ">=6" } }, + "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 + }, "node_modules/@sentry/hub": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", @@ -2213,6 +2100,12 @@ "node": ">=6" } }, + "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 + }, "node_modules/@sentry/minimal": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", @@ -2227,6 +2120,12 @@ "node": ">=6" } }, + "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 + }, "node_modules/@sentry/node": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", @@ -2247,6 +2146,12 @@ "node": ">=6" } }, + "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 + }, "node_modules/@sentry/tracing": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", @@ -2263,6 +2168,12 @@ "node": ">=6" } }, + "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 + }, "node_modules/@sentry/types": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", @@ -2285,22 +2196,10 @@ "node": ">=6" } }, - "node_modules/@smithy/types": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.2.2.tgz", - "integrity": "sha512-4PS0y1VxDnELGHGgBWlDksB2LJK8TG8lcvlWxIsgR+8vROI7Ms8h1P4FQUx+ftAX2QZv5g1CJCdhdRmQKyonyw==", - "dev": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "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 }, "node_modules/@solidity-parser/parser": { @@ -2340,10 +2239,10 @@ "dev": true, "peer": true }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", + "node_modules/@typechain/ethers-v6": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.4.3.tgz", + "integrity": "sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==", "dev": true, "peer": true, "dependencies": { @@ -2351,68 +2250,25 @@ "ts-essentials": "^7.0.1" }, "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" + "ethers": "6.x", + "typechain": "^8.3.1", + "typescript": ">=4.7.0" } }, "node_modules/@typechain/hardhat": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.6.tgz", - "integrity": "sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-8.0.3.tgz", + "integrity": "sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==", "dev": true, "peer": true, "dependencies": { "fs-extra": "^9.1.0" }, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@typechain/ethers-v5": "^10.2.1", - "ethers": "^5.4.7", + "@typechain/ethers-v6": "^0.4.3", + "ethers": "^6.1.0", "hardhat": "^2.9.9", - "typechain": "^8.1.1" - } - }, - "node_modules/@typechain/hardhat/node_modules/fs-extra": { - "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", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typechain/hardhat/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, - "peer": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@typechain/hardhat/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" + "typechain": "^8.3.1" } }, "node_modules/@types/bn.js": { @@ -2547,7 +2403,8 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", - "dev": true + "dev": true, + "peer": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -2579,30 +2436,6 @@ "node": ">=12" } }, - "node_modules/abstract-level/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -2646,10 +2479,11 @@ } }, "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 + "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", @@ -2692,19 +2526,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/amazon-cognito-identity-js": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.5.tgz", - "integrity": "sha512-bRAiw6uQuttufRD0TFcrWvA5hxAgPIwNzM0crmWniPdkmCxRoa68yxRaViZUbwAcGu9YPLCLqM87b1060BRddw==", - "dev": true, - "dependencies": { - "@aws-crypto/sha256-js": "1.2.2", - "buffer": "4.9.2", - "fast-base64-decode": "^1.0.0", - "isomorphic-unfetch": "^3.0.0", - "js-cookie": "^2.2.1" - } - }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -2844,25 +2665,6 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.3.tgz", - "integrity": "sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.reduce": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", @@ -2883,14 +2685,15 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "get-intrinsic": "^1.2.1", "is-array-buffer": "^3.0.2", "is-shared-array-buffer": "^1.0.2" @@ -2958,15 +2761,6 @@ "dev": true, "peer": true }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, - "dependencies": { - "retry": "0.13.1" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3019,17 +2813,6 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", "dev": true }, - "node_modules/axios": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", - "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3230,14 +3013,27 @@ } }, "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, "node_modules/buffer-from": { @@ -3651,12 +3447,6 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "node_modules/compare-versions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", - "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", - "dev": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4131,6 +3921,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-array-method-boxes-properly": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", @@ -4151,15 +3959,6 @@ "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -4328,6 +4127,12 @@ "@scure/base": "~1.1.0" } }, + "node_modules/eth-gas-reporter/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 + }, "node_modules/eth-gas-reporter/node_modules/ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", @@ -4721,21 +4526,6 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "node_modules/eth-gas-reporter/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/eth-gas-reporter/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -5059,6 +4849,7 @@ "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", "bn.js": "^5.1.2", @@ -5071,53 +4862,41 @@ } }, "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.7.1.tgz", + "integrity": "sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==", "dev": true, "funding": [ { "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "url": "https://github.com/sponsors/ethers-io/" }, { "type": "individual", "url": "https://www.buymeacoffee.com/ricmoo" } ], + "peer": true, "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@adraffy/ens-normalize": "1.9.2", + "@noble/hashes": "1.1.2", + "@noble/secp256k1": "1.7.1", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, + "node_modules/ethers/node_modules/@types/node": { + "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", @@ -5197,12 +4976,6 @@ "node >=0.6.0" ] }, - "node_modules/fast-base64-decode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", - "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==", - "dev": true - }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -5375,17 +5148,17 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 6" + "node": ">= 0.12" } }, "node_modules/fp-ts": { @@ -5395,17 +5168,19 @@ "dev": true }, "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "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": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=10" } }, "node_modules/fs-readdir-recursive": { @@ -5978,6 +5753,59 @@ "@scure/bip39": "1.1.1" } }, + "node_modules/hardhat/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "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" + } + }, + "node_modules/hardhat/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, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/hardhat/node_modules/ws": { + "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" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -6234,15 +6062,6 @@ "node": ">= 6" } }, - "node_modules/i": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", - "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6344,7 +6163,8 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "peer": true }, "node_modules/internal-slot": { "version": "1.0.5", @@ -6710,16 +6530,6 @@ "node": ">=0.10.0" } }, - "node_modules/isomorphic-unfetch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", - "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.1", - "unfetch": "^4.2.0" - } - }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -6735,12 +6545,6 @@ "node": ">=10" } }, - "node_modules/js-cookie": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", - "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", - "dev": true - }, "node_modules/js-sdsl": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", @@ -6832,10 +6636,14 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -6937,30 +6745,6 @@ "node": ">=12" } }, - "node_modules/level-transcoder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -7007,6 +6791,20 @@ "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 + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -7566,26 +7364,6 @@ "semver": "bin/semver" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-gyp-build": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", @@ -7609,3147 +7387,33 @@ "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, + "peer": true, "engines": { - "node": ">=12.19" - } - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm": { - "version": "9.8.1", - "resolved": "https://registry.npmjs.org/npm/-/npm-9.8.1.tgz", - "integrity": "sha512-AfDvThQzsIXhYgk9zhbk5R+lh811lKkLAeQMMhSypf1BM7zUafeIIBzMzespeuVEJ0+LvY36oRQYf7IKLzU3rw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/run-script", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "cli-table3", - "columnify", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "npmlog", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "sigstore", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "dev": true, - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^6.3.0", - "@npmcli/config": "^6.2.1", - "@npmcli/fs": "^3.1.0", - "@npmcli/map-workspaces": "^3.0.4", - "@npmcli/package-json": "^4.0.1", - "@npmcli/promise-spawn": "^6.0.2", - "@npmcli/run-script": "^6.0.2", - "abbrev": "^2.0.0", - "archy": "~1.0.0", - "cacache": "^17.1.3", - "chalk": "^5.3.0", - "ci-info": "^3.8.0", - "cli-columns": "^4.0.0", - "cli-table3": "^0.6.3", - "columnify": "^1.6.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.2", - "glob": "^10.2.7", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^6.1.1", - "ini": "^4.1.1", - "init-package-json": "^5.0.0", - "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^3.0.0", - "libnpmaccess": "^7.0.2", - "libnpmdiff": "^5.0.19", - "libnpmexec": "^6.0.3", - "libnpmfund": "^4.0.19", - "libnpmhook": "^9.0.3", - "libnpmorg": "^5.0.4", - "libnpmpack": "^5.0.19", - "libnpmpublish": "^7.5.0", - "libnpmsearch": "^6.0.2", - "libnpmteam": "^5.0.3", - "libnpmversion": "^4.0.2", - "make-fetch-happen": "^11.1.1", - "minimatch": "^9.0.3", - "minipass": "^5.0.0", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^9.4.0", - "nopt": "^7.2.0", - "npm-audit-report": "^5.0.0", - "npm-install-checks": "^6.1.1", - "npm-package-arg": "^10.1.0", - "npm-pick-manifest": "^8.0.1", - "npm-profile": "^7.0.1", - "npm-registry-fetch": "^14.0.5", - "npm-user-validate": "^2.0.0", - "npmlog": "^7.0.1", - "p-map": "^4.0.0", - "pacote": "^15.2.0", - "parse-conflict-json": "^3.0.1", - "proc-log": "^3.0.0", - "qrcode-terminal": "^0.12.0", - "read": "^2.1.0", - "semver": "^7.5.4", - "sigstore": "^1.7.0", - "ssri": "^10.0.4", - "supports-color": "^9.4.0", - "tar": "^6.1.15", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^5.0.0", - "which": "^3.0.1", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@colors/colors": { - "version": "1.5.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "6.3.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^3.1.0", - "@npmcli/installed-package-contents": "^2.0.2", - "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^5.0.0", - "@npmcli/name-from-folder": "^2.0.0", - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^4.0.0", - "@npmcli/query": "^3.0.0", - "@npmcli/run-script": "^6.0.0", - "bin-links": "^4.0.1", - "cacache": "^17.0.4", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^6.1.1", - "json-parse-even-better-errors": "^3.0.0", - "json-stringify-nice": "^1.1.4", - "minimatch": "^9.0.0", - "nopt": "^7.0.0", - "npm-install-checks": "^6.0.0", - "npm-package-arg": "^10.1.0", - "npm-pick-manifest": "^8.0.1", - "npm-registry-fetch": "^14.0.3", - "npmlog": "^7.0.1", - "pacote": "^15.0.8", - "parse-conflict-json": "^3.0.0", - "proc-log": "^3.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.2", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^10.0.1", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^3.0.2", - "ci-info": "^3.8.0", - "ini": "^4.1.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/disparity-colors": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "4.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "bin": { - "installed-package-contents": "lib/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "3.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^2.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0", - "read-package-json-fast": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^17.0.0", - "json-parse-even-better-errors": "^3.0.0", - "pacote": "^15.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^4.1.0", - "glob": "^10.2.2", - "hosted-git-info": "^6.1.1", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "proc-log": "^3.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.1.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.1.0", - "tuf-js": "^1.1.7" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tootallnate/once": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/models": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abort-controller": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/npm/node_modules/agentkeepalive": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/are-we-there-yet": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^4.1.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/base64-js": { - "version": "1.5.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "read-cmd-shim": "^4.0.0", - "write-file-atomic": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/buffer": { - "version": "6.0.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/npm/node_modules/builtins": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "17.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "3.8.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^4.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cli-table3": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/npm/node_modules/clone": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/color-support": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/npm/node_modules/columnify": { - "version": "1.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/console-control-strings": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/defaults": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/delegates": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/depd": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/npm/node_modules/diff": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/event-target-shim": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/events": { - "version": "3.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/gauge": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.2.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" - }, - "bin": { - "glob": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/has": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/npm/node_modules/has-unicode": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "6.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/humanize-ms": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ieee754": { - "version": "1.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "6.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/ini": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^10.0.0", - "promzard": "^1.0.0", - "read": "^2.0.0", - "read-package-json": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/ip": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^3.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/is-core-module": { - "version": "2.12.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^10.1.0", - "npm-registry-fetch": "^14.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "5.0.19", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^6.3.0", - "@npmcli/disparity-colors": "^3.0.0", - "@npmcli/installed-package-contents": "^2.0.2", - "binary-extensions": "^2.2.0", - "diff": "^5.1.0", - "minimatch": "^9.0.0", - "npm-package-arg": "^10.1.0", - "pacote": "^15.0.8", - "tar": "^6.1.13" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "6.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^6.3.0", - "@npmcli/run-script": "^6.0.0", - "ci-info": "^3.7.1", - "npm-package-arg": "^10.1.0", - "npmlog": "^7.0.1", - "pacote": "^15.0.8", - "proc-log": "^3.0.0", - "read": "^2.0.0", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "4.0.19", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^6.3.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "9.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^14.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "5.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^14.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "5.0.19", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^6.3.0", - "@npmcli/run-script": "^6.0.0", - "npm-package-arg": "^10.1.0", - "pacote": "^15.0.8" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "7.5.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^3.6.1", - "normalize-package-data": "^5.0.0", - "npm-package-arg": "^10.1.0", - "npm-registry-fetch": "^14.0.3", - "proc-log": "^3.0.0", - "semver": "^7.3.7", - "sigstore": "^1.4.0", - "ssri": "^10.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^14.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "5.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^14.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^4.0.1", - "@npmcli/run-script": "^6.0.0", - "json-parse-even-better-errors": "^3.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "7.18.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "11.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-json-stream": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "9.4.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/abbrev": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { - "version": "3.0.7", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/node-gyp/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "7.2.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "6.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "10.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "7.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^6.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "8.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "7.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "14.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npmlog": { - "version": "7.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/once": { - "version": "1.4.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/pacote": { - "version": "15.2.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^5.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.3.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.9.2", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^9.1.1", - "minipass": "^5.0.0 || ^6.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.0.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/process": { - "version": "0.11.10", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "^2.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~1.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json": { - "version": "6.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/readable-stream": { - "version": "4.4.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "1.7.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.1.0", - "@sigstore/tuf": "^1.0.1", - "make-fetch-happen": "^11.0.1" - }, - "bin": { - "sigstore": "bin/sigstore.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.7.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.13", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/ssri": { - "version": "10.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/string_decoder": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.1.15", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js": { - "version": "1.1.7", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/wcwidth": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/npm/node_modules/which": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/wide-align": { - "version": "1.1.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.19" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", "dev": true, - "inBundle": true, - "license": "MIT", + "peer": true, "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" + "abbrev": "1" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "bin": { + "nopt": "bin/nopt.js" } }, - "node_modules/npm/node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "5.0.1", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, "node_modules/number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -10809,21 +7473,18 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.getownpropertydescriptors": { @@ -11109,30 +7770,6 @@ "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", @@ -11174,30 +7811,6 @@ "pino-pretty": "bin.js" } }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/pino-pretty/node_modules/readable-stream": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", @@ -11437,32 +8050,6 @@ "asap": "~2.0.6" } }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proper-lockfile/node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/proxy-from-env": { - "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 - }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -11724,20 +8311,6 @@ "request": "^2.34" } }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/request/node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -11793,15 +8366,6 @@ "node": ">=4" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -11901,13 +8465,13 @@ "dev": true }, "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -12217,12 +8781,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -12542,15 +9100,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/solidity-ast": { - "version": "0.4.52", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.52.tgz", - "integrity": "sha512-iOya9BSiB9jhM8Vf40n8lGELGzwrUc57rl5BhfNtJ5cvAaMvRcNlHeAMNvqJJyjoUnczqRbHqdivEqK89du3Cw==", - "dev": true, - "dependencies": { - "array.prototype.findlast": "^1.2.2" - } - }, "node_modules/solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", @@ -12827,6 +9376,16 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/solidity-coverage/node_modules/jsonfile": { + "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" + } + }, "node_modules/solidity-coverage/node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -12944,22 +9503,6 @@ "dev": true, "peer": true }, - "node_modules/solidity-coverage/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "peer": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/solidity-coverage/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -13079,6 +9622,16 @@ "node": ">=6" } }, + "node_modules/solidity-coverage/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" + } + }, "node_modules/solidity-coverage/node_modules/wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -13544,20 +10097,6 @@ "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", "dev": 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, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/thread-stream": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.0.tgz", @@ -13623,12 +10162,6 @@ "node": ">=0.8" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "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", @@ -13786,10 +10319,11 @@ } }, "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 + "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", @@ -13881,6 +10415,21 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/typechain/node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -13902,6 +10451,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typechain/node_modules/jsonfile": { + "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" + } + }, "node_modules/typechain/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -13915,6 +10474,16 @@ "node": ">=10" } }, + "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" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", @@ -14051,19 +10620,14 @@ "node": ">=14.0" } }, - "node_modules/unfetch": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", - "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", - "dev": true - }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, + "peer": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -14178,6 +10742,19 @@ "node": ">=8.0.0" } }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/web3-utils/node_modules/ethereum-cryptography": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", @@ -14191,22 +10768,6 @@ "@scure/bip39": "1.2.1" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -14416,12 +10977,13 @@ "dev": true }, "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "dev": true, + "peer": true, "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", diff --git a/package.json b/package.json index f1ac2c2..0c17a54 100644 --- a/package.json +++ b/package.json @@ -18,16 +18,12 @@ "devDependencies": { "@babel/register": "^7.22.5", "@faker-js/faker": "^8.0.2", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@openzeppelin/contracts": "^4.8.3", - "@openzeppelin/contracts-upgradeable": "^4.8.3", - "@openzeppelin/hardhat-upgrades": "^1.25.0", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@openzeppelin/contracts": "^4.9.3", "dotenv": "^16.3.1", "hardhat": "^2.14.0", "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.9", - "i": "^0.3.7", - "npm": "^9.8.1", "pino": "^8.15.0", "pino-pretty": "^10.2.0", "prettier": "^2.8.8", diff --git a/test/ERC20DaoPool.spec.ts b/test/ERC20DaoPool.spec.ts index 724ab98..65aac9b 100644 --- a/test/ERC20DaoPool.spec.ts +++ b/test/ERC20DaoPool.spec.ts @@ -36,23 +36,25 @@ describe('ERC20DaoPool test', function () { it('should deposit ERC-20 tokens to pool', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); - await token.approve(daoPool.address, parseTokensUnits(1)); - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(0)); + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, parseTokensUnits(1)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(0)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(0)); //when await daoPool.deposit(parseTokensUnits(1)); //then - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(1)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(1)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(1)); }); it('should deposit multiple times ERC-20 tokens to pool', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); - await token.approve(daoPool.address, parseTokensUnits(3)); - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(0)); + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, parseTokensUnits(3)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(0)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(0)); //when @@ -61,7 +63,7 @@ describe('ERC20DaoPool test', function () { await daoPool.deposit(parseTokensUnits(1)); //then - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(3)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(3)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(3)); }); }); @@ -78,8 +80,9 @@ describe('ERC20DaoPool test', function () { it('should vote for on proposal', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(1)); + await token.approve(daoPoolAddress, parseTokensUnits(1)); await daoPool.deposit(parseTokensUnits(1)); await daoPool.approveProposal(proposal.address); @@ -96,8 +99,9 @@ describe('ERC20DaoPool test', function () { it('should vote against on proposal', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(1)); + await token.approve(daoPoolAddress, parseTokensUnits(1)); await daoPool.deposit(parseTokensUnits(1)); await daoPool.approveProposal(proposal.address); @@ -114,8 +118,9 @@ describe('ERC20DaoPool test', function () { it('should revert when vote twice', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(1)); + await token.approve(daoPoolAddress, parseTokensUnits(1)); await daoPool.deposit(parseTokensUnits(1)); await daoPool.approveProposal(proposal.address); const proposalDaoPool = daoPool.connect(proposal); @@ -140,7 +145,8 @@ describe('ERC20DaoPool test', function () { it('should revert when withdraw token amount too big', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); - await token.approve(daoPool.address, parseTokensUnits(10)); + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, parseTokensUnits(10)); await daoPool.deposit(parseTokensUnits(10)); //when and then @@ -150,8 +156,9 @@ describe('ERC20DaoPool test', function () { it('should revert when user (msg.sender) votes in active proposals', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(1)); + await token.approve(daoPoolAddress, parseTokensUnits(1)); await daoPool.deposit(parseTokensUnits(1)); await daoPool.approveProposal(proposal.address); const proposalDaoPool = daoPool.connect(proposal); @@ -164,11 +171,12 @@ describe('ERC20DaoPool test', function () { it('should withdraw some of user (msg.sender) tokens in pool', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(10)); + await token.approve(daoPoolAddress, parseTokensUnits(10)); await daoPool.deposit(parseTokensUnits(10)); await daoPool.approveProposal(proposal.address); - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(10)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(10)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(10)); const accountTokensBalanceBefore = await token.balanceOf(account.address); @@ -177,20 +185,21 @@ describe('ERC20DaoPool test', function () { await daoPool.withdraw(parseTokensUnits(3), account.address); //then - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(7)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(7)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(7)); const accountTokensBalanceAfter = await token.balanceOf(account.address); - expect(accountTokensBalanceAfter.sub(accountTokensBalanceBefore)).to.eq(parseTokensUnits(3)); + expect(accountTokensBalanceAfter - accountTokensBalanceBefore).to.eq(parseTokensUnits(3)); }); it('should withdraw all of user (msg.sender) when withdraw half of tokens twice ', async function () { //given const { daoPool, token, account } = await loadFixture(erc20DaoPoolFixture); + const daoPoolAddress = await daoPool.getAddress(); const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, parseTokensUnits(10)); + await token.approve(daoPoolAddress, parseTokensUnits(10)); await daoPool.deposit(parseTokensUnits(10)); await daoPool.approveProposal(proposal.address); - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(10)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(10)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(10)); const accountTokensBalanceBefore = await token.balanceOf(account.address); @@ -200,10 +209,10 @@ describe('ERC20DaoPool test', function () { await daoPool.withdraw(parseTokensUnits(6), account.address); //then - expect(await token.balanceOf(daoPool.address)).to.eq(parseTokensUnits(0)); + expect(await token.balanceOf(daoPoolAddress)).to.eq(parseTokensUnits(0)); expect(await daoPool.balanceOf(account.address)).to.eq(parseTokensUnits(0)); const accountTokensBalanceAfter = await token.balanceOf(account.address); - expect(accountTokensBalanceAfter.sub(accountTokensBalanceBefore)).to.eq(parseTokensUnits(10)); + expect(accountTokensBalanceAfter -accountTokensBalanceBefore).to.eq(parseTokensUnits(10)); }); }); @@ -220,9 +229,11 @@ describe('ERC20DaoPool test', function () { it('should revert when proposal not ended yet', async function () { //given const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( dao, - token.address, + tokenAddress, generateRandomProposalId(), generateRandomMerkleRoot(), otherAccount.address, @@ -231,15 +242,18 @@ describe('ERC20DaoPool test', function () { ); //when and then - await expect(ERC20DaoPool.resolveProposal(proposal.address)).to.revertedWith('Proposal not ended'); + const proposalAddress = await proposal.getAddress(); + await expect(ERC20DaoPool.resolveProposal(proposalAddress)).to.revertedWith('Proposal not ended'); }); it('should resolve proposal without token votes', async function () { //given const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( dao, - token.address, + tokenAddress, generateRandomProposalId(), generateRandomMerkleRoot(), otherAccount.address, @@ -247,48 +261,52 @@ describe('ERC20DaoPool test', function () { '5' ); await waitForProposalToEnd(proposal); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(true); + const proposalAddress = await proposal.getAddress(); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(true); //when - await ERC20DaoPool.resolveProposal(proposal.address); + await ERC20DaoPool.resolveProposal(proposalAddress); //then - expect((await ERC20DaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await ERC20DaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(false); + expect((await ERC20DaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await ERC20DaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(false); expect(await ERC20DaoPool.voterActiveProposals(account.address)).to.eq(0); - expect(await ERC20DaoPool.balanceOf(proposal.address)).to.eq(parseTokensUnits(0)); + expect(await ERC20DaoPool.balanceOf(proposalAddress)).to.eq(parseTokensUnits(0)); }); it('should resolve proposal with token vote for won side', async function () { //given const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); const proposal = await createSendErc20Proposal( dao, - token.address, + tokenAddress, generateRandomProposalId(), generateRandomMerkleRoot(), otherAccount.address, generateRandomIntNumberFrom1To100(), '5' ); - await approveErc20(token, ERC20DaoPool.address, 100); + const erc20DaoPoolAddress = await ERC20DaoPool.getAddress(); + const proposalAddress = await proposal.getAddress(); + await approveErc20(token, erc20DaoPoolAddress, 100); await depositTokensToPool(ERC20DaoPool, 100); await proposal.voteWithToken(true); await waitForProposalToEnd(proposal); - expect((await ERC20DaoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await ERC20DaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(true); + expect((await ERC20DaoPool.getProposalForVoters(proposalAddress)).length).to.eq(1); + expect((await ERC20DaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(true); expect(await ERC20DaoPool.voterActiveProposals(account.address)).to.eq(1); expect(await ERC20DaoPool.balanceOf(account.address)).to.eq(parseTokensUnits(100)); //when - await ERC20DaoPool.resolveProposal(proposal.address); + await ERC20DaoPool.resolveProposal(proposalAddress); //then - expect((await ERC20DaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await ERC20DaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(false); + expect((await ERC20DaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await ERC20DaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(false); expect(await ERC20DaoPool.voterActiveProposals(account.address)).to.eq(0); expect(await ERC20DaoPool.balanceOf(account.address)).to.eq(parseTokensUnits(100)); }); @@ -296,51 +314,55 @@ describe('ERC20DaoPool test', function () { it('should resolve proposal with token vote for lost side (voter loose everything)', async function () { //given const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); const proposal = await createSendErc20Proposal( dao, - token.address, + tokenAddress, generateRandomProposalId(), generateRandomMerkleRoot(), otherAccount.address, generateRandomIntNumberFrom1To100(), '5' ); - await approveErc20(token, ERC20DaoPool.address, 300); + const erc20DaoPoolAddress = await ERC20DaoPool.getAddress(); + await approveErc20(token, erc20DaoPoolAddress, 300); await depositTokensToPool(ERC20DaoPool, 300); await proposal.voteWithToken(true); await transferERC20TokensToAddress(token, otherAccount.address, 200); const tokenByOtherAccount = token.connect(otherAccount); - await approveErc20(tokenByOtherAccount, ERC20DaoPool.address, 200); + await approveErc20(tokenByOtherAccount, erc20DaoPoolAddress, 200); const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); await depositTokensToPool(daoPoolByOtherAccount, 200); const proposalByOtherAccount = proposal.connect(otherAccount); await proposalByOtherAccount.voteWithToken(false); await waitForProposalToEnd(proposal); - expect((await ERC20DaoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await ERC20DaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(1); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(true); + const proposalAddress = await proposal.getAddress(); + expect((await ERC20DaoPool.getProposalForVoters(proposalAddress)).length).to.eq(1); + expect((await ERC20DaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(1); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(true); expect(await ERC20DaoPool.voterActiveProposals(account.address)).to.eq(1); expect(await ERC20DaoPool.voterActiveProposals(otherAccount.address)).to.eq(1); expect(await ERC20DaoPool.balanceOf(account.address)).to.eq(parseTokensUnits(300)); expect(await ERC20DaoPool.balanceOf(otherAccount.address)).to.eq(parseTokensUnits(200)); - const tokensBalanceOfDaoBeforeResolveProposal = await token.balanceOf(dao.address); + const daoAddress = await dao.getAddress(); + const tokensBalanceOfDaoBeforeResolveProposal = await token.balanceOf(daoAddress); //when - await ERC20DaoPool.resolveProposal(proposal.address); + await ERC20DaoPool.resolveProposal(proposalAddress); //then - expect((await ERC20DaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await ERC20DaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await ERC20DaoPool.approvedProposals(proposal.address)).to.eq(false); + expect((await ERC20DaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await ERC20DaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await ERC20DaoPool.approvedProposals(proposalAddress)).to.eq(false); expect(await ERC20DaoPool.voterActiveProposals(account.address)).to.eq(0); expect(await ERC20DaoPool.voterActiveProposals(otherAccount.address)).to.eq(0); expect(await ERC20DaoPool.balanceOf(account.address)).to.eq(parseTokensUnits(300)); expect(await ERC20DaoPool.balanceOf(otherAccount.address)).to.eq(parseTokensUnits(0)); expect(await token.balanceOf(otherAccount.address)).to.eq(parseTokensUnits(0)); // dao receives lost user tokens - const tokensBalanceOfDaoAfterResolveProposal = await token.balanceOf(dao.address); - expect(tokensBalanceOfDaoAfterResolveProposal.sub(tokensBalanceOfDaoBeforeResolveProposal)).to.eq(parseTokensUnits(200)); + const tokensBalanceOfDaoAfterResolveProposal = await token.balanceOf(daoAddress); + expect(tokensBalanceOfDaoAfterResolveProposal - tokensBalanceOfDaoBeforeResolveProposal).to.eq(parseTokensUnits(200)); }); }); }); diff --git a/test/NFTDaoPool.spec.ts b/test/NFTDaoPool.spec.ts index 4c421bf..5148764 100644 --- a/test/NFTDaoPool.spec.ts +++ b/test/NFTDaoPool.spec.ts @@ -1,13 +1,13 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { - deployNftToken, - generateRandomIntNumberFrom1To100, - generateRandomMerkleRoot, - generateRandomProposalId, - initializeErc20TokenAndDaoFixture, - initializeNftTokenAndDaoFixture, - mintNft, - waitForProposalToEnd, + deployNftToken, + generateRandomIntNumberFrom1To100, + generateRandomMerkleRoot, + generateRandomProposalId, + initializeErc20TokenAndDaoFixture, + initializeNftTokenAndDaoFixture, + mintNft, + waitForProposalToEnd, } from './utils/utils'; import { createNftDaoPool } from './utils/dao-pool-utils'; import { expect } from 'chai'; @@ -16,348 +16,367 @@ import { ERC721Development } from '../typechain-types'; import { createSendErc20Proposal } from './utils/proposal-utils'; const nftDaoPool = async () => { - const token = await deployNftToken(); - const daoPool = await createNftDaoPool(token); - const account = (await ethers.getSigners())[0]; - const devToken = token as ERC721Development; - await mintNft(devToken, account.address); - return { token, daoPool, account }; + const token = await deployNftToken(); + const daoPool = await createNftDaoPool(token); + const account = (await ethers.getSigners())[0]; + const devToken = token as ERC721Development; + await mintNft(devToken, account.address); + return {token, daoPool, account}; }; network.provider.send('evm_setIntervalMining', [500]); describe('NFTDaoPool test', function () { - describe('deposit', async function () { - it('should revert deposit NFT tokens when invalid token id', async function () { - //given - const { daoPool } = await loadFixture(nftDaoPool); - - //when and then - await expect(daoPool.deposit(1)).to.be.revertedWith('ERC721: caller is not token owner or approved'); - }); - - it('should deposit NFT tokens to pool', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - await token.approve(daoPool.address, 1); - expect(await token.balanceOf(account.address)).to.eq(1); - expect(await token.balanceOf(daoPool.address)).to.eq(0); - expect(await daoPool.balanceOf(account.address)).to.eq(0); - - //when - await daoPool.deposit(1); - - //then - expect(await token.balanceOf(account.address)).to.eq(0); - expect(await token.balanceOf(daoPool.address)).to.eq(1); - expect(await daoPool.balanceOf(account.address)).to.eq(1); - }); - - it('should deposit multiple times NFT tokens to pool', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - await mintNft(token as ERC721Development, account.address); - await token.approve(daoPool.address, 1); - await token.approve(daoPool.address, 2); - expect(await token.balanceOf(account.address)).to.eq(2); - expect(await token.balanceOf(daoPool.address)).to.eq(0); - expect(await daoPool.balanceOf(account.address)).to.eq(0); - - //when - await daoPool.deposit(1); - await daoPool.deposit(2); - - //then - expect(await token.balanceOf(account.address)).to.eq(0); - expect(await token.balanceOf(daoPool.address)).to.eq(2); - expect(await daoPool.balanceOf(account.address)).to.eq(2); - }); - }); - - describe('vote', async function () { - it('should revert when proposal not approved', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - - //when and then - await expect(daoPool.vote(account.address, true)).to.be.revertedWith('Proposal not approved'); - }); - - it('should vote for on proposal', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await daoPool.deposit(1); - await daoPool.approveProposal(proposal.address); - - //when - const proposalDaoPool = daoPool.connect(proposal); - await proposalDaoPool.vote(account.address, true); - - //then - expect((await daoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await daoPool.getProposalForVoters(proposal.address))[0]).to.eq(account.address); - expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); - }); - - it('should vote against on proposal', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await daoPool.deposit(1); - await daoPool.approveProposal(proposal.address); - - //when - const proposalDaoPool = daoPool.connect(proposal); - await proposalDaoPool.vote(account.address, false); - - //then - expect((await daoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(1); - expect((await daoPool.getProposalAgainstVoters(proposal.address))[0]).to.eq(account.address); - expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); - }); - - it('should revert when vote twice', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await daoPool.deposit(1); - await daoPool.approveProposal(proposal.address); - const proposalDaoPool = daoPool.connect(proposal); - await proposalDaoPool.vote(account.address, true); - - //when and then - await expect(proposalDaoPool.vote(account.address, true)).to.revertedWith('Already voted'); - expect((await daoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await daoPool.getProposalForVoters(proposal.address))[0]).to.eq(account.address); - expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); - }); - }); - describe('withdraw', async function () { - it('should revert when user (msg.sender) has 0 tokens in pool', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - - //when and then - await expect(daoPool.withdraw(1, account.address)).to.revertedWith('Token not found'); + describe('deposit', async function () { + it('should revert deposit NFT tokens when invalid token id', async function () { + //given + const {daoPool} = await loadFixture(nftDaoPool); + //when and then + await expect(daoPool.deposit(1)).to.be.revertedWith('ERC721: caller is not token owner or approved'); + }); + + it('should deposit NFT tokens to pool', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, 1); + expect(await token.balanceOf(account.address)).to.eq(1); + expect(await token.balanceOf(daoPoolAddress)).to.eq(0); + expect(await daoPool.balanceOf(account.address)).to.eq(0); + + //when + await daoPool.deposit(1); + + //then + expect(await token.balanceOf(account.address)).to.eq(0); + expect(await token.balanceOf(daoPoolAddress)).to.eq(1); + expect(await daoPool.balanceOf(account.address)).to.eq(1); + }); + + it('should deposit multiple times NFT tokens to pool', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const daoPoolAddress = await daoPool.getAddress(); + await mintNft(token as ERC721Development, account.address); + await token.approve(daoPoolAddress, 1); + await token.approve(daoPoolAddress, 2); + expect(await token.balanceOf(account.address)).to.eq(2); + expect(await token.balanceOf(daoPoolAddress)).to.eq(0); + expect(await daoPool.balanceOf(account.address)).to.eq(0); + + //when + await daoPool.deposit(1); + await daoPool.deposit(2); + + //then + expect(await token.balanceOf(account.address)).to.eq(0); + expect(await token.balanceOf(daoPoolAddress)).to.eq(2); + expect(await daoPool.balanceOf(account.address)).to.eq(2); + }); }); - it('should revert when user (msg.sender) doesnt own given token ID', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - await token.approve(daoPool.address, 1); - await daoPool.deposit(1); - - //when and then - await expect(daoPool.withdraw(2, account.address)).to.revertedWith('Token not found'); - }); - - it('should revert when user (msg.sender) votes in active proposals', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await daoPool.deposit(1); - await daoPool.approveProposal(proposal.address); - const proposalDaoPool = daoPool.connect(proposal); - await proposalDaoPool.vote(account.address, true); - - //when and then - await expect(daoPool.withdraw(1, account.address)).to.revertedWith('User has active proposals'); - }); - - it('should withdraw some of user (msg.sender) tokens in pool', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - await mintNft(token as ERC721Development, account.address); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await token.approve(daoPool.address, 2); - await daoPool.deposit(1); - await daoPool.deposit(2); - await daoPool.approveProposal(proposal.address); - expect(await token.balanceOf(daoPool.address)).to.eq(2); - expect(await daoPool.balanceOf(account.address)).to.eq(2); - - const accountTokensBalanceBefore = await token.balanceOf(account.address); - - //when - await daoPool.withdraw(1, account.address); - - //then - expect(await token.balanceOf(daoPool.address)).to.eq(1); - expect(await daoPool.balanceOf(account.address)).to.eq(1); - const accountTokensBalanceAfter = await token.balanceOf(account.address); - expect(accountTokensBalanceAfter.sub(accountTokensBalanceBefore)).to.eq(1); - }); - - it('should withdraw 2 of user (msg.sender) when withdraw 2 times', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - await mintNft(token as ERC721Development, account.address); - const proposal = (await ethers.getSigners())[1]; - await token.approve(daoPool.address, 1); - await token.approve(daoPool.address, 2); - await daoPool.deposit(1); - await daoPool.deposit(2); - await daoPool.approveProposal(proposal.address); - expect(await token.balanceOf(daoPool.address)).to.eq(2); - expect(await daoPool.balanceOf(account.address)).to.eq(2); - - const accountTokensBalanceBefore = await token.balanceOf(account.address); - - //when - await daoPool.withdraw(1, account.address); - await daoPool.withdraw(2, account.address); - - //then - expect(await token.balanceOf(daoPool.address)).to.eq(0); - expect(await daoPool.balanceOf(account.address)).to.eq(0); - const accountTokensBalanceAfter = await token.balanceOf(account.address); - expect(accountTokensBalanceAfter.sub(accountTokensBalanceBefore)).to.eq(2); + describe('vote', async function () { + it('should revert when proposal not approved', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + + //when and then + await expect(daoPool.vote(account.address, true)).to.be.revertedWith('Proposal not approved'); + }); + + it('should vote for on proposal', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const daoPoolAddress = await daoPool.getAddress(); + const proposal = (await ethers.getSigners())[1]; + await token.approve(daoPoolAddress, 1); + await daoPool.deposit(1); + await daoPool.approveProposal(proposal.address); + + //when + const proposalDaoPool = daoPool.connect(proposal); + await proposalDaoPool.vote(account.address, true); + + //then + expect((await daoPool.getProposalForVoters(proposal.address)).length).to.eq(1); + expect((await daoPool.getProposalForVoters(proposal.address))[0]).to.eq(account.address); + expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); + }); + + it('should vote against on proposal', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const proposal = (await ethers.getSigners())[1]; + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, 1); + await daoPool.deposit(1); + await daoPool.approveProposal(proposal.address); + + //when + const proposalDaoPool = daoPool.connect(proposal); + await proposalDaoPool.vote(account.address, false); + + //then + expect((await daoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(1); + expect((await daoPool.getProposalAgainstVoters(proposal.address))[0]).to.eq(account.address); + expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); + }); + + it('should revert when vote twice', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const proposal = (await ethers.getSigners())[1]; + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, 1); + await daoPool.deposit(1); + await daoPool.approveProposal(proposal.address); + const proposalDaoPool = daoPool.connect(proposal); + await proposalDaoPool.vote(account.address, true); + + //when and then + await expect(proposalDaoPool.vote(account.address, true)).to.revertedWith('Already voted'); + expect((await daoPool.getProposalForVoters(proposal.address)).length).to.eq(1); + expect((await daoPool.getProposalForVoters(proposal.address))[0]).to.eq(account.address); + expect(await daoPool.voterActiveProposals(account.address)).to.eq(1); + }); }); - }); - - describe('resolveProposal', async function () { - it('should revert when proposal not approved', async function () { - //given - const { daoPool, token, account } = await loadFixture(nftDaoPool); - - //when and then - //account.address as proposal address - await expect(daoPool.resolveProposal(account.address)).to.revertedWith('Proposal not approved'); - }); - - it('should revert when proposal not ended yet', async function () { - //given - const { token, dao, account, otherAccount, NFTDaoPool } = await loadFixture(initializeNftTokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100(), - '5' - ); - - //when and then - await expect(NFTDaoPool.resolveProposal(proposal.address)).to.revertedWith('Proposal not ended'); - }); - - it('should resolve proposal without token votes', async function () { - //given - const { token, dao, account, otherAccount, NFTDaoPool } = await loadFixture(initializeNftTokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100(), - '5' - ); - await waitForProposalToEnd(proposal); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(true); - - //when - await NFTDaoPool.resolveProposal(proposal.address); - - //then - expect((await NFTDaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await NFTDaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(false); - expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); - expect(await NFTDaoPool.balanceOf(proposal.address)).to.eq(0); - }); - - it('should resolve proposal with token vote for won side', async function () { - //given - const { token, dao, account, otherAccount, NFTDaoPool } = await loadFixture(initializeNftTokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100(), - '5' - ); - await mintNft(token as ERC721Development, account.address); - await token.approve(NFTDaoPool.address, 1); - await NFTDaoPool.deposit(1); - await proposal.voteWithToken(true); - await waitForProposalToEnd(proposal); - - expect((await NFTDaoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await NFTDaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(true); - expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(1); - expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); - - //when - await NFTDaoPool.resolveProposal(proposal.address); - - //then - expect((await NFTDaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await NFTDaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(false); - expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); - expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); + describe('withdraw', async function () { + it('should revert when user (msg.sender) has 0 tokens in pool', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + + //when and then + await expect(daoPool.withdraw(1, account.address)).to.revertedWith('Token not found'); + }); + + it('should revert when user (msg.sender) doesnt own given token ID', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, 1); + await daoPool.deposit(1); + + //when and then + await expect(daoPool.withdraw(2, account.address)).to.revertedWith('Token not found'); + }); + + it('should revert when user (msg.sender) votes in active proposals', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const proposal = (await ethers.getSigners())[1]; + const daoPoolAddress = await daoPool.getAddress(); + await token.approve(daoPoolAddress, 1); + await daoPool.deposit(1); + await daoPool.approveProposal(proposal.address); + const proposalDaoPool = daoPool.connect(proposal); + await proposalDaoPool.vote(account.address, true); + + //when and then + await expect(daoPool.withdraw(1, account.address)).to.revertedWith('User has active proposals'); + }); + + it('should withdraw some of user (msg.sender) tokens in pool', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + await mintNft(token as ERC721Development, account.address); + const daoPoolAddress = await daoPool.getAddress(); + const proposal = (await ethers.getSigners())[1]; + await token.approve(daoPoolAddress, 1); + await token.approve(daoPoolAddress, 2); + await daoPool.deposit(1); + await daoPool.deposit(2); + await daoPool.approveProposal(proposal.address); + expect(await token.balanceOf(daoPoolAddress)).to.eq(2); + expect(await daoPool.balanceOf(account.address)).to.eq(2); + + const accountTokensBalanceBefore = await token.balanceOf(account.address); + + //when + await daoPool.withdraw(1, account.address); + + //then + expect(await token.balanceOf(daoPoolAddress)).to.eq(1); + expect(await daoPool.balanceOf(account.address)).to.eq(1); + const accountTokensBalanceAfter = await token.balanceOf(account.address); + expect(accountTokensBalanceAfter - accountTokensBalanceBefore).to.eq(1); + }); + + it('should withdraw 2 of user (msg.sender) when withdraw 2 times', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + const daoPoolAddress = await daoPool.getAddress(); + await mintNft(token as ERC721Development, account.address); + const proposal = (await ethers.getSigners())[1]; + await token.approve(daoPoolAddress, 1); + await token.approve(daoPoolAddress, 2); + await daoPool.deposit(1); + await daoPool.deposit(2); + await daoPool.approveProposal(proposal.address); + expect(await token.balanceOf(daoPoolAddress)).to.eq(2); + expect(await daoPool.balanceOf(account.address)).to.eq(2); + + const accountTokensBalanceBefore = await token.balanceOf(account.address); + + //when + await daoPool.withdraw(1, account.address); + await daoPool.withdraw(2, account.address); + + //then + expect(await token.balanceOf(daoPoolAddress)).to.eq(0); + expect(await daoPool.balanceOf(account.address)).to.eq(0); + const accountTokensBalanceAfter = await token.balanceOf(account.address); + expect(accountTokensBalanceAfter - accountTokensBalanceBefore).to.eq(2); + }); }); - it('should resolve proposal with token vote for lost side (voter loose everything)', async function () { - //given - const { token, dao, account, otherAccount, NFTDaoPool } = await loadFixture(initializeNftTokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100(), - '5' - ); - await mintNft(token as ERC721Development, account.address); - await token.approve(NFTDaoPool.address, 1); - await NFTDaoPool.deposit(1); - await proposal.voteWithToken(true); - - const tokenByOtherAccount = token.connect(otherAccount); - await mintNft(tokenByOtherAccount as ERC721Development, otherAccount.address); - await tokenByOtherAccount.approve(NFTDaoPool.address, 2); - const daoPoolByOtherAccount = NFTDaoPool.connect(otherAccount); - await daoPoolByOtherAccount.deposit(2); - const proposalByOtherAccount = proposal.connect(otherAccount); - await proposalByOtherAccount.voteWithToken(false); - - await waitForProposalToEnd(proposal); - expect((await NFTDaoPool.getProposalForVoters(proposal.address)).length).to.eq(1); - expect((await NFTDaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(1); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(true); - expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(1); - expect(await NFTDaoPool.voterActiveProposals(otherAccount.address)).to.eq(1); - expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); - expect(await NFTDaoPool.balanceOf(otherAccount.address)).to.eq(1); - const tokensBalanceOfDaoBeforeResolveProposal = await token.balanceOf(dao.address); - - //when - await NFTDaoPool.resolveProposal(proposal.address); - - //then - expect((await NFTDaoPool.getProposalForVoters(proposal.address)).length).to.eq(0); - expect((await NFTDaoPool.getProposalAgainstVoters(proposal.address)).length).to.eq(0); - expect(await NFTDaoPool.approvedProposals(proposal.address)).to.eq(false); - expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); - expect(await NFTDaoPool.voterActiveProposals(otherAccount.address)).to.eq(0); - expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); - expect(await NFTDaoPool.balanceOf(otherAccount.address)).to.eq(0); - expect(await token.balanceOf(otherAccount.address)).to.eq(0); - // dao receives lost user tokens - const tokensBalanceOfDaoAfterResolveProposal = await token.balanceOf(dao.address); - expect(tokensBalanceOfDaoAfterResolveProposal.sub(tokensBalanceOfDaoBeforeResolveProposal)).to.eq(1); + describe('resolveProposal', async function () { + it('should revert when proposal not approved', async function () { + //given + const {daoPool, token, account} = await loadFixture(nftDaoPool); + + //when and then + //account.address as proposal address + await expect(daoPool.resolveProposal(account.address)).to.revertedWith('Proposal not approved'); + }); + + it('should revert when proposal not ended yet', async function () { + //given + const {token, dao, account, otherAccount, NFTDaoPool} = await loadFixture(initializeNftTokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100(), + '5' + ); + + //when and then + const proposalAddress = await proposal.getAddress(); + await expect(NFTDaoPool.resolveProposal(proposalAddress)).to.revertedWith('Proposal not ended'); + }); + + it('should resolve proposal without token votes', async function () { + //given + const {token, dao, account, otherAccount, NFTDaoPool} = await loadFixture(initializeNftTokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100(), + '5' + ); + await waitForProposalToEnd(proposal); + const proposalAddress = await proposal.getAddress(); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(true); + + //when + await NFTDaoPool.resolveProposal(proposalAddress); + + //then + expect((await NFTDaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await NFTDaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(false); + expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); + expect(await NFTDaoPool.balanceOf(proposalAddress)).to.eq(0); + }); + + it('should resolve proposal with token vote for won side', async function () { + //given + const {token, dao, account, otherAccount, NFTDaoPool} = await loadFixture(initializeNftTokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const nftDaoPoolAddress = await NFTDaoPool.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100(), + '5' + ); + await mintNft(token as ERC721Development, account.address); + await token.approve(nftDaoPoolAddress, 1); + await NFTDaoPool.deposit(1); + await proposal.voteWithToken(true); + await waitForProposalToEnd(proposal); + const proposalAddress = await proposal.getAddress(); + + expect((await NFTDaoPool.getProposalForVoters(proposalAddress)).length).to.eq(1); + expect((await NFTDaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(true); + expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(1); + expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); + + //when + await NFTDaoPool.resolveProposal(proposalAddress); + + //then + expect((await NFTDaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await NFTDaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(false); + expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); + expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); + }); + + it('should resolve proposal with token vote for lost side (voter loose everything)', async function () { + //given + const {token, dao, account, otherAccount, NFTDaoPool} = await loadFixture(initializeNftTokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100(), + '5' + ); + await mintNft(token as ERC721Development, account.address); + const nftDaoPoolAddress = await NFTDaoPool.getAddress(); + await token.approve(nftDaoPoolAddress, 1); + await NFTDaoPool.deposit(1); + await proposal.voteWithToken(true); + + const tokenByOtherAccount = token.connect(otherAccount); + await mintNft(tokenByOtherAccount as ERC721Development, otherAccount.address); + await tokenByOtherAccount.approve(nftDaoPoolAddress, 2); + const daoPoolByOtherAccount = NFTDaoPool.connect(otherAccount); + await daoPoolByOtherAccount.deposit(2); + const proposalByOtherAccount = proposal.connect(otherAccount); + await proposalByOtherAccount.voteWithToken(false); + + await waitForProposalToEnd(proposal); + const proposalAddress = await proposal.getAddress(); + expect((await NFTDaoPool.getProposalForVoters(proposalAddress)).length).to.eq(1); + expect((await NFTDaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(1); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(true); + expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(1); + expect(await NFTDaoPool.voterActiveProposals(otherAccount.address)).to.eq(1); + expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); + expect(await NFTDaoPool.balanceOf(otherAccount.address)).to.eq(1); + const daoAddress = await dao.getAddress(); + const tokensBalanceOfDaoBeforeResolveProposal = await token.balanceOf(daoAddress); + + //when + await NFTDaoPool.resolveProposal(proposalAddress); + + //then + expect((await NFTDaoPool.getProposalForVoters(proposalAddress)).length).to.eq(0); + expect((await NFTDaoPool.getProposalAgainstVoters(proposalAddress)).length).to.eq(0); + expect(await NFTDaoPool.approvedProposals(proposalAddress)).to.eq(false); + expect(await NFTDaoPool.voterActiveProposals(account.address)).to.eq(0); + expect(await NFTDaoPool.voterActiveProposals(otherAccount.address)).to.eq(0); + expect(await NFTDaoPool.balanceOf(account.address)).to.eq(1); + expect(await NFTDaoPool.balanceOf(otherAccount.address)).to.eq(0); + expect(await token.balanceOf(otherAccount.address)).to.eq(0); + // dao receives lost user tokens + const tokensBalanceOfDaoAfterResolveProposal = await token.balanceOf(daoAddress); + expect(tokensBalanceOfDaoAfterResolveProposal - tokensBalanceOfDaoBeforeResolveProposal).to.eq(1); + }); }); - }); }); diff --git a/test/Proposal.spec.ts b/test/Proposal.spec.ts index 0b09906..5adfd5c 100644 --- a/test/Proposal.spec.ts +++ b/test/Proposal.spec.ts @@ -2,482 +2,511 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers, network } from 'hardhat'; import { - deployErc20Dao, - expectBalanceDiffIsGte, - expectBalanceNotChanged, - generateRandomIntNumberFrom1To100, - generateRandomMerkleRoot, - generateRandomProposalId, - initializeErc20TokenAndDaoFixture, - initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens, - sleep, - waitForProposalToEnd, + deployErc20Dao, + expectBalanceDiffIsGte, + expectBalanceNotChanged, + generateRandomIntNumberFrom1To100, + generateRandomMerkleRoot, + generateRandomProposalId, + initializeErc20TokenAndDaoFixture, + initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens, + sleep, + waitForProposalToEnd, } from './utils/utils'; import { - createSendErc20Proposal, - createProposalWithTokensTx, - encodeSendErc20TokensTx, - expectProposalVoteResults, - voteOnProposalWithCollateral, - voteOnProposalWithTokenCollateral, + createSendErc20Proposal, + createProposalWithTokensTx, + encodeSendErc20TokensTx, + expectProposalVoteResults, + voteOnProposalWithCollateral, + voteOnProposalWithTokenCollateral, } from './utils/proposal-utils'; import { CHALLENGE_PERIOD_SECONDS, NATIVE_COLLATERAL, TOKEN_COLLATERAL } from './test-constants'; -import { BigNumber } from 'ethers'; // SETUP for faster mining network.provider.send('evm_setIntervalMining', [500]); describe('Proposal test', function () { - describe('creation', function () { - it('should initialize correct ERC-20 proposal', async function () { - //given fresh deployment to verify all properties including timestamps - const { token, dao, account, otherAccount, ERC20DaoPool } = await initializeErc20TokenAndDaoFixture(); - const tokenTransferAmount = generateRandomIntNumberFrom1To100(); - const proposalId = generateRandomProposalId(); - const proposalMerkleRootHex = generateRandomMerkleRoot(); - const sendDaoTokensTx = encodeSendErc20TokensTx(dao, proposalId, token.address, otherAccount.address, tokenTransferAmount); - - //when - const proposal = await createProposalWithTokensTx(dao, proposalId, proposalMerkleRootHex, sendDaoTokensTx); - - //then - // it assumes block mining to be done ~10 second - const nowInSeconds = Math.floor(new Date().getTime() / 1000); - const before = BigNumber.from(nowInSeconds - 10); - const after = BigNumber.from(nowInSeconds + 10); - const contractionCreationTime = await proposal.contractCreationTime(); - expect(contractionCreationTime, 'Expecting contractCreationTime after correct').to.be.gte(before); - expect(contractionCreationTime, 'Expecting contractCreationTime before correct').to.be.lte(after); - expect(await proposal.proposalMerkleRootHex(), 'Expecting proposalMerkleRootHex correct').to.eq(proposalMerkleRootHex); - expect(await proposal.sequencerAddress(), 'Expecting sequencerAddress correct').to.eq(account.address); - expect(await proposal.challengePeriodSeconds(), 'Expecting challengePeriodSeconds correct').to.eq(CHALLENGE_PERIOD_SECONDS); - expect(await proposal.nativeCollateral(), 'Expecting nativeCollateral correct').to.eq(NATIVE_COLLATERAL); - expect(await proposal.tokenCollateral(), 'Expecting tokenCollateral correct').to.eq(TOKEN_COLLATERAL); - expect((await proposal.getPayloads()).length, 'Expecting getPayloads length correct').to.eq(1); - expect((await proposal.getPayloads())[0], 'Expecting getPayloads correct').to.eq(sendDaoTokensTx); - expect(await proposal.daoAddress(), 'Expecting daoAddress correct').to.eq(dao.address); - expect(await proposal.daoPool(), 'Expecting daoPool correct').to.eq(ERC20DaoPool.address); - expect(await proposal.forVotesCounter(), 'Expecting forVotesCounter correct').to.eq(1); - expect(await proposal.againstVotesCounter(), 'Expecting againstVotesCounter correct').to.eq(0); - expect(await proposal.executed(), 'Expecting executed correct').to.be.false; - expect(await proposal.isEnded(), 'Expecting isEnded correct').to.be.false; - expect(await proposal.isPassed(), 'Expecting isPassed correct').to.be.false; + describe('creation', function () { + it('should initialize correct ERC-20 proposal', async function () { + //given fresh deployment to verify all properties including timestamps + const {token, dao, account, otherAccount, ERC20DaoPool} = await initializeErc20TokenAndDaoFixture(); + const tokenAddress = await token.getAddress(); + const daoAddress = dao.getAddress(); + const erc20DaoPoolAddress = ERC20DaoPool.getAddress(); + const tokenTransferAmount = generateRandomIntNumberFrom1To100(); + const proposalId = generateRandomProposalId(); + const proposalMerkleRootHex = generateRandomMerkleRoot(); + const sendDaoTokensTx = encodeSendErc20TokensTx(dao, proposalId, tokenAddress, otherAccount.address, tokenTransferAmount); + + //when + const proposal = await createProposalWithTokensTx(dao, proposalId, proposalMerkleRootHex, sendDaoTokensTx); + + //then + // it assumes block mining to be done ~10 second + const nowInSeconds = Math.floor(new Date().getTime() / 1000); + const before = nowInSeconds - 10; + const after = nowInSeconds + 10; + const contractionCreationTime = await proposal.contractCreationTime(); + expect(contractionCreationTime, 'Expecting contractCreationTime after correct').to.be.gte(before); + expect(contractionCreationTime, 'Expecting contractCreationTime before correct').to.be.lte(after); + expect(await proposal.proposalMerkleRootHex(), 'Expecting proposalMerkleRootHex correct').to.eq(proposalMerkleRootHex); + expect(await proposal.sequencerAddress(), 'Expecting sequencerAddress correct').to.eq(account.address); + expect(await proposal.challengePeriodSeconds(), 'Expecting challengePeriodSeconds correct').to.eq(CHALLENGE_PERIOD_SECONDS); + expect(await proposal.nativeCollateral(), 'Expecting nativeCollateral correct').to.eq(NATIVE_COLLATERAL); + expect(await proposal.tokenCollateral(), 'Expecting tokenCollateral correct').to.eq(TOKEN_COLLATERAL); + expect((await proposal.getPayloads()).length, 'Expecting getPayloads length correct').to.eq(1); + expect((await proposal.getPayloads())[0], 'Expecting getPayloads correct').to.eq(sendDaoTokensTx); + expect(await proposal.daoAddress(), 'Expecting daoAddress correct').to.eq(daoAddress); + expect(await proposal.daoPool(), 'Expecting daoPool correct').to.eq(erc20DaoPoolAddress); + expect(await proposal.forVotesCounter(), 'Expecting forVotesCounter correct').to.eq(1); + expect(await proposal.againstVotesCounter(), 'Expecting againstVotesCounter correct').to.eq(0); + expect(await proposal.executed(), 'Expecting executed correct').to.be.false; + expect(await proposal.isEnded(), 'Expecting isEnded correct').to.be.false; + expect(await proposal.isPassed(), 'Expecting isPassed correct').to.be.false; + }); + + it('should create proposal with 5 ETH collateral', async function () { + //given + const {dao, token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100(), + '5' + ); + //when and then + const vote = await proposal.votes(account.address); + expectProposalVoteResults(vote, 5, 0, 0, 0); + }); + + it('should revert when creating proposal with 0 ETH collateral', async function () { + const {dao} = await loadFixture(initializeErc20TokenAndDaoFixture); + await expect(dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [])).to.be.revertedWith('Collateral too small'); + }); + + it('should revert when creating proposal with too small collateral (0.1 ETH)', async function () { + const {dao} = await loadFixture(initializeErc20TokenAndDaoFixture); + await expect( + dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [], { + value: ethers.parseEther('0.1'), + }) + ).to.be.revertedWith('Collateral too small'); + }); + + it('should revert when creating proposal with incorrect collateral (1.2 ETH - not multiplication of required collateral)', async function () { + const {dao} = await loadFixture(initializeErc20TokenAndDaoFixture); + await expect( + dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [], { + value: ethers.parseEther('1.2'), + }) + ).to.be.revertedWith('Collateral incorrect'); + }); }); - it('should create proposal with 5 ETH collateral', async function () { - //given - const { dao, token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100(), - '5' - ); - //when and then - const vote = await proposal.votes(account.address); - expectProposalVoteResults(vote, 5, 0, 0, 0); + describe('vote, voteWithToken', function () { + it('should increment voter votes when vote for (5 ETH vote)', async function () { + //given + const {dao, token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 5, 0, 0, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('6')); + }); + + it('should increment voter votes when vote for 3 times (3x5 ETH vote)', async function () { + //given + const {dao, token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); + await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); + await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 15, 0, 0, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('16')); + }); + + it('should increment voter votes when vote against (5 ETH vote)', async function () { + //given + const {dao, token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithCollateral(proposalByOtherAccount, false, 5); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 0, 5, 0, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('6')); + }); + + it('should set votes once when vote for with 500 token collateral 3 times (expecting 5 votes)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 0, 0, 5, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('1')); + }); + + it('should increment voter votes when vote for with 500 token collateral (5 votes)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 0, 0, 5, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('1')); + }); + + it('should increment voter votes when vote against with 500 token collateral (5 votes)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 0, 0, 0, 5); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('1')); + }); + + it('should increment voter votes when vote for and against (10 ETH votes total)', async function () { + //given + const {dao, token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); + await voteOnProposalWithCollateral(proposalByOtherAccount, false, 5); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 5, 5, 0, 0); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('11')); + }); + + it('should increment voter votes when vote for and against with 500 token collateral (10 votes total)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + const proposalByOtherAccount = proposal.connect(otherAccount); + + //when + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); + await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + + //then + const vote = await proposal.votes(otherAccount.address); + expectProposalVoteResults(vote, 0, 0, 5, 5); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('1')); + }); + + it('should revert when vote with 1 ETH collateral after proposal challenge time ended', async function () { + //given + const {token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const {dao} = await deployErc20Dao(tokenAddress, 1); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalByOtherAccount = proposal.connect(otherAccount); + await sleep(1000); + + //when and then + await expect(voteOnProposalWithCollateral(proposalByOtherAccount, true, 1)).to.be.revertedWith('Is not in challenge period'); + }); + + it('should revert when vote with 500 tokens collateral after proposal challenge time ended', async function () { + //given + const {token, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const {dao} = await deployErc20Dao(tokenAddress, 1); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalByOtherAccount = proposal.connect(otherAccount); + await sleep(1000); + + //when and then + await expect(voteOnProposalWithTokenCollateral(proposalByOtherAccount, false)).to.be.revertedWith('Is not in challenge period'); + }); }); - it('should revert when creating proposal with 0 ETH collateral', async function () { - const { dao } = await loadFixture(initializeErc20TokenAndDaoFixture); - await expect(dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [])).to.be.revertedWith('Collateral too small'); + describe('claimReward', function () { + it('should revert when claiming reward before proposal ended', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + + //when and then + await expect(proposal.claimReward()).to.be.revertedWith('Is not after challenge period'); + }); + + it('should revert when claiming reward when reward not apply', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalByOtherAccount = proposal.connect(otherAccount); + await waitForProposalToEnd(proposalByOtherAccount); + + //when and then + await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); + }); + + it('should reward proposal creator only once (when no voters)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + await waitForProposalToEnd(proposal); + + const creatorAddressBeforeClaim = await ethers.provider.getBalance(account.address); + + //when + await proposal.claimReward(); + + //then + expect(proposal); + expectBalanceDiffIsGte(creatorAddressBeforeClaim, await ethers.provider.getBalance(account.address), 1); + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('0')); + + //when and then + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + }); + + it('should reward challenger only once and not reward creator when 1:1', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + + const proposalByOtherAccount = proposal.connect(otherAccount); + await voteOnProposalWithCollateral(proposalByOtherAccount, false, 2); + await waitForProposalToEnd(proposal); + + const creatorBalanceBeforeClaim = await ethers.provider.getBalance(account.address); + const otherAccountBalanceBeforeClaim = await ethers.provider.getBalance(otherAccount.address); + + //when and then + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await proposalByOtherAccount.claimReward(); + + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('0')); + expectBalanceDiffIsGte(otherAccountBalanceBeforeClaim, await ethers.provider.getBalance(otherAccount.address), 3); + expectBalanceNotChanged(creatorBalanceBeforeClaim, await ethers.provider.getBalance(account.address)); + + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); + }); + + it('should reward against voters only once and not for voters when 2:3 (3 votes against)', async function () { + //given + const {dao, token, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); + const tokenAddress = await token.getAddress(); + + const signers = await ethers.getSigners(); + const otherAccount2 = signers[2]; + const otherAccount3 = signers[3]; + const otherAccount4 = signers[4]; + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + + const proposalByOtherAccount = proposal.connect(otherAccount); + const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, true, 1); + + const proposalByOtherAccount2 = proposal.connect(otherAccount2); + const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, false, 1); + + const proposalByOtherAccount3 = proposal.connect(otherAccount3); + const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); + + const proposalByOtherAccount4 = proposal.connect(otherAccount4); + const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); + + await Promise.all([res1, res2, res3, res4]); + + await waitForProposalToEnd(proposal); + + const creatorBalanceBeforeClaim = await ethers.provider.getBalance(account.address); + const otherAccountBalanceBeforeClaim = await ethers.provider.getBalance(otherAccount.address); + const otherAccount2BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount2.address); + const otherAccount3BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount3.address); + const otherAccount4BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount4.address); + + //when and then + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); + await proposalByOtherAccount2.claimReward(); + await proposalByOtherAccount3.claimReward(); + await proposalByOtherAccount4.claimReward(); + + expect(await ethers.provider.getBalance(proposalAddress)).to.eq(ethers.parseEther('0')); + expectBalanceNotChanged(creatorBalanceBeforeClaim, await ethers.provider.getBalance(account.address)); + expectBalanceNotChanged(otherAccountBalanceBeforeClaim, await ethers.provider.getBalance(otherAccount.address)); + expectBalanceDiffIsGte(otherAccount2BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount2.address), 1); + expectBalanceDiffIsGte(otherAccount3BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount3.address), 1); + expectBalanceDiffIsGte(otherAccount4BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount4.address), 1); + + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount2.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); + }); }); - - it('should revert when creating proposal with too small collateral (0.1 ETH)', async function () { - const { dao } = await loadFixture(initializeErc20TokenAndDaoFixture); - await expect( - dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [], { - value: ethers.utils.parseEther('0.1'), - }) - ).to.be.revertedWith('Collateral too small'); - }); - - it('should revert when creating proposal with incorrect collateral (1.2 ETH - not multiplication of required collateral)', async function () { - const { dao } = await loadFixture(initializeErc20TokenAndDaoFixture); - await expect( - dao.createProposal(generateRandomProposalId(), generateRandomMerkleRoot(), [], { - value: ethers.utils.parseEther('1.2'), - }) - ).to.be.revertedWith('Collateral incorrect'); - }); - }); - - describe('vote, voteWithToken', function () { - it('should increment voter votes when vote for (5 ETH vote)', async function () { - //given - const { dao, token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 5, 0, 0, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('6')); - }); - - it('should increment voter votes when vote for 3 times (3x5 ETH vote)', async function () { - //given - const { dao, token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); - await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); - await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 15, 0, 0, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('16')); - }); - - it('should increment voter votes when vote against (5 ETH vote)', async function () { - //given - const { dao, token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithCollateral(proposalByOtherAccount, false, 5); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 0, 5, 0, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('6')); - }); - - it('should set votes once when vote for with 500 token collateral 3 times (expecting 5 votes)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 0, 0, 5, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('1')); - }); - - it('should increment voter votes when vote for with 500 token collateral (5 votes)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 0, 0, 5, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('1')); - }); - - it('should increment voter votes when vote against with 500 token collateral (5 votes)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 0, 0, 0, 5); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('1')); - }); - - it('should increment voter votes when vote for and against (10 ETH votes total)', async function () { - //given - const { dao, token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithCollateral(proposalByOtherAccount, true, 5); - await voteOnProposalWithCollateral(proposalByOtherAccount, false, 5); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 5, 5, 0, 0); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('11')); - }); - - it('should increment voter votes when vote for and against with 500 token collateral (10 votes total)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - - //when - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); - await voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - - //then - const vote = await proposal.votes(otherAccount.address); - expectProposalVoteResults(vote, 0, 0, 5, 5); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('1')); - }); - - it('should revert when vote with 1 ETH collateral after proposal challenge time ended', async function () { - //given - const { token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const { dao } = await deployErc20Dao(token.address, 1); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - await sleep(1000); - - //when and then - await expect(voteOnProposalWithCollateral(proposalByOtherAccount, true, 1)).to.be.revertedWith('Is not in challenge period'); - }); - - it('should revert when vote with 500 tokens collateral after proposal challenge time ended', async function () { - //given - const { token, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const { dao } = await deployErc20Dao(token.address, 1); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - await sleep(1000); - - //when and then - await expect(voteOnProposalWithTokenCollateral(proposalByOtherAccount, false)).to.be.revertedWith('Is not in challenge period'); - }); - }); - - describe('claimReward', function () { - it('should revert when claiming reward before proposal ended', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - - //when and then - await expect(proposal.claimReward()).to.be.revertedWith('Is not after challenge period'); - }); - - it('should revert when claiming reward when reward not apply', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - const proposalByOtherAccount = proposal.connect(otherAccount); - await waitForProposalToEnd(proposalByOtherAccount); - - //when and then - await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); - }); - - it('should reward proposal creator only once (when no voters)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - await waitForProposalToEnd(proposal); - - const creatorAddressBeforeClaim = await ethers.provider.getBalance(account.address); - - //when - await proposal.claimReward(); - - //then - expect(proposal); - expectBalanceDiffIsGte(creatorAddressBeforeClaim, await ethers.provider.getBalance(account.address), 1); - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('0')); - - //when and then - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - }); - - it('should reward challenger only once and not reward creator when 1:1', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - - const proposalByOtherAccount = proposal.connect(otherAccount); - await voteOnProposalWithCollateral(proposalByOtherAccount, false, 2); - await waitForProposalToEnd(proposal); - - const creatorBalanceBeforeClaim = await ethers.provider.getBalance(account.address); - const otherAccountBalanceBeforeClaim = await ethers.provider.getBalance(otherAccount.address); - - //when and then - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await proposalByOtherAccount.claimReward(); - - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('0')); - expectBalanceDiffIsGte(otherAccountBalanceBeforeClaim, await ethers.provider.getBalance(otherAccount.address), 3); - expectBalanceNotChanged(creatorBalanceBeforeClaim, await ethers.provider.getBalance(account.address)); - - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); - }); - - it('should reward against voters only once and not for voters when 2:3 (3 votes against)', async function () { - //given - const { dao, token, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens); - - const signers = await ethers.getSigners(); - const otherAccount2 = signers[2]; - const otherAccount3 = signers[3]; - const otherAccount4 = signers[4]; - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - - const proposalByOtherAccount = proposal.connect(otherAccount); - const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, true, 1); - - const proposalByOtherAccount2 = proposal.connect(otherAccount2); - const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, false, 1); - - const proposalByOtherAccount3 = proposal.connect(otherAccount3); - const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); - - const proposalByOtherAccount4 = proposal.connect(otherAccount4); - const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); - - await Promise.all([res1, res2, res3, res4]); - - await waitForProposalToEnd(proposal); - - const creatorBalanceBeforeClaim = await ethers.provider.getBalance(account.address); - const otherAccountBalanceBeforeClaim = await ethers.provider.getBalance(otherAccount.address); - const otherAccount2BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount2.address); - const otherAccount3BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount3.address); - const otherAccount4BalanceBeforeClaim = await ethers.provider.getBalance(otherAccount4.address); - - //when and then - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); - await proposalByOtherAccount2.claimReward(); - await proposalByOtherAccount3.claimReward(); - await proposalByOtherAccount4.claimReward(); - - expect(await ethers.provider.getBalance(proposal.address)).to.eq(ethers.utils.parseEther('0')); - expectBalanceNotChanged(creatorBalanceBeforeClaim, await ethers.provider.getBalance(account.address)); - expectBalanceNotChanged(otherAccountBalanceBeforeClaim, await ethers.provider.getBalance(otherAccount.address)); - expectBalanceDiffIsGte(otherAccount2BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount2.address), 1); - expectBalanceDiffIsGte(otherAccount3BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount3.address), 1); - expectBalanceDiffIsGte(otherAccount4BalanceBeforeClaim, await ethers.provider.getBalance(otherAccount4.address), 1); - - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount2.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); - }); - }); }); diff --git a/test/ProposalScenarios.spec.ts b/test/ProposalScenarios.spec.ts index af19bff..ff6c20c 100644 --- a/test/ProposalScenarios.spec.ts +++ b/test/ProposalScenarios.spec.ts @@ -2,411 +2,422 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers, network } from 'hardhat'; import { - deployNftToken, - expectBalanceDiffIsGte, - expectBalanceNotChanged, - expectTokenBalanceToEq, - generateRandomIntNumberFrom1To100, - generateRandomMerkleRoot, - generateRandomProposalId, - initializeErc20TokenAndDaoFixture, - waitForProposalToEnd, + deployNftToken, + expectBalanceDiffIsGte, + expectBalanceNotChanged, + expectTokenBalanceToEq, + generateRandomIntNumberFrom1To100, + generateRandomMerkleRoot, + generateRandomProposalId, + initializeErc20TokenAndDaoFixture, + waitForProposalToEnd, } from './utils/utils'; import { - checkProposalIsExecuted, - checkProposalIsPassed, - createSendErc20Proposal, createSendEthCryptoProposal, - createSendNftProposal, - voteOnProposalWithCollateral + checkProposalIsExecuted, + checkProposalIsPassed, + createSendErc20Proposal, createSendEthCryptoProposal, + createSendNftProposal, + voteOnProposalWithCollateral } from './utils/proposal-utils'; import { LOGGER } from './utils/pino-logger-service'; import { ERC721Development, Proposal } from '../typechain-types'; -import { erc721 } from '../typechain-types/@openzeppelin/contracts/token'; -import { parseEther } from 'ethers/lib/utils'; // SETUP for faster mining network.provider.send('evm_setIntervalMining', [500]); describe('Proposal scenarios', function () { - const daoTokensBalance = 1000; - - describe('Proposal passed scenarios', function () { - it('should pass with 1:0 (only creator vote)', async function () { - const { token, dao, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - - const tokenTransferAmount = generateRandomIntNumberFrom1To100(); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - tokenTransferAmount - ); - - await waitForProposalToEnd(proposal); - - LOGGER.info('2. Verify proposal is passed and not executed'); - await checkProposalIsPassed(proposal, true); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance); - await expectTokenBalanceToEq(token, otherAccount.address, 0); - - LOGGER.info('4. Execute proposal'); - await proposal.executeProposal(); - - LOGGER.info('5. Verify proposal is executed'); - await checkProposalIsExecuted(proposal, true); - - LOGGER.info('6. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance - Number(tokenTransferAmount)); - await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); - - LOGGER.info('7. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - - LOGGER.info('8. Claim rewards by all accounts'); - await proposal.claimReward(); - - LOGGER.info('9. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - - LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); - expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); - - LOGGER.info('11. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); - }); - - // this test covers correctness of NFT asset type DAO transfer tx - it('should pass with 1:0 (only creator vote) - NFT transfer from DAO', async function () { - const { dao, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - const nftToken = await deployNftToken(); - await (nftToken as ERC721Development).createNFT(dao.address, ''); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendNftProposal( - dao, - nftToken.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - 1 - ); - - await waitForProposalToEnd(proposal); - - LOGGER.info('2. Verify proposal is passed and not executed'); - await checkProposalIsPassed(proposal, true); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); - expect(await nftToken.balanceOf(dao.address)).to.eq(1); - expect(await nftToken.balanceOf(otherAccount.address)).to.eq(0); - - LOGGER.info('4. Execute proposal'); - await proposal.executeProposal(); - - LOGGER.info('5. Verify proposal is executed'); - await checkProposalIsExecuted(proposal, true); - - LOGGER.info('6. Verify accounts NFT token balances after executing proposal: DAO lost 1 NFT, other account has 1 new NFT'); - expect(await nftToken.balanceOf(dao.address)).to.eq(0); - expect(await nftToken.balanceOf(otherAccount.address)).to.eq(1); - - LOGGER.info('7. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - - LOGGER.info('8. Claim rewards by all accounts'); - await proposal.claimReward(); - - LOGGER.info('9. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - - LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); - expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); - - LOGGER.info('11. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); - }); - - // this test covers correctness of ETH asset type DAO transfer tx - it('should pass with 1:0 (only creator vote) - ETH transfer from DAO', async function () { - const {dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); - // send 1 eth from account to dao - await account.sendTransaction({ - to: dao.address, - value: parseEther('1') - }); - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendEthCryptoProposal( - dao, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - 0.3 - ); - - await waitForProposalToEnd(proposal); - - LOGGER.info('2. Verify proposal is passed and not executed'); - await checkProposalIsPassed(proposal, true); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); - expect(await ethers.provider.getBalance(dao.address)).to.eq(parseEther('1')); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - - LOGGER.info('4. Execute proposal'); - await proposal.executeProposal(); - - LOGGER.info('5. Verify proposal is executed'); - await checkProposalIsExecuted(proposal, true); - - LOGGER.info('6. Verify ETH balances of DAO and other account after executing proposal: DAO has less ETH, other account has more ETH'); - expect(await ethers.provider.getBalance(dao.address)).to.eq(parseEther('0.7')); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - expect(balanceOfOtherAccountAfter.sub(balanceOfOtherAccountBefore)).to.eq(parseEther('0.3')); - - LOGGER.info('7. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - - LOGGER.info('8. Claim rewards by all accounts'); - await proposal.claimReward(); - - LOGGER.info('9. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - - LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); - expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); - - LOGGER.info('11. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); - }) - - - it('should pass with 3:2 (3 votes for)', async function () { - const { token, dao, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - - const signers = await ethers.getSigners(); - const otherAccount2 = signers[2]; - const otherAccount3 = signers[3]; - const otherAccount4 = signers[4]; - - const tokenTransferAmount = generateRandomIntNumberFrom1To100(); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - tokenTransferAmount - ); - - LOGGER.info('2. Vote 2 votes for (including initial creator vote it will be 3) and 2 votes against'); - const proposalByOtherAccount = proposal.connect(otherAccount); - const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, true, 1); - - const proposalByOtherAccount2 = proposal.connect(otherAccount2); - const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, true, 1); - - const proposalByOtherAccount3 = proposal.connect(otherAccount3); - const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); - - const proposalByOtherAccount4 = proposal.connect(otherAccount4); - const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); - - await Promise.all([res1, res2, res3, res4]); - - await waitForProposalToEnd(proposal); - - LOGGER.info('3. Verify proposal is passed and not executed'); - await checkProposalIsPassed(proposal, true); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('4. Verify accounts ERC20 token balances before executing proposal'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance); - await expectTokenBalanceToEq(token, otherAccount.address, 0); - - LOGGER.info('5. Execute proposal'); - await proposal.executeProposal(); - - LOGGER.info('6. Verify proposal is executed'); - await checkProposalIsExecuted(proposal, true); - - LOGGER.info('7. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance - Number(tokenTransferAmount)); - await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); - - LOGGER.info('8. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info('9. Claim rewards by all accounts (voters against should revert)'); - await proposal.claimReward(); - await proposalByOtherAccount.claimReward(); - await proposalByOtherAccount2.claimReward(); - await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); - - LOGGER.info('10. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); - - // 11. Expected for voting accounts: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH - LOGGER.info( - '11. Expected for voters balance: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH. Against voters should get 0 and pay claim tx fee' - ); - expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1.66); - expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 1.66); - expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 1.66); - expectBalanceNotChanged(balanceOfOtherAccount3Before, balanceOfOtherAccount3After); - expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); - - LOGGER.info('12. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); - }); - }); - - describe('Proposal not pass scenarios', function () { - it('should not pass when 1:1 (creator vote and vote against)', async function () { - const { token, dao, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - - LOGGER.info('2. Other account votes against'); - const proposalByOtherAccount: Proposal = proposal.connect(otherAccount) as Proposal; - await voteOnProposalWithCollateral(proposalByOtherAccount, false, 1); - - await waitForProposalToEnd(proposal); - - LOGGER.info('3. Execute proposal should fail'); - await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); - - LOGGER.info('4. Verify proposal is not passed and not executed'); - await checkProposalIsPassed(proposal, false); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('5. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - - LOGGER.info('6. Claim rewards by all accounts'); - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await proposalByOtherAccount.claimReward(); - - LOGGER.info('7. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - - LOGGER.info('8. Expected voter against balance: 1 ETH collateral back + 1 ETH reward = 2 ETH. Creator should get 0 and pay claim tx fee'); - expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); - expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 2); - - LOGGER.info('9. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); + const daoTokensBalance = 1000; + + describe('Proposal passed scenarios', function () { + it('should pass with 1:0 (only creator vote)', async function () { + const {token, dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const daoAddress = await dao.getAddress(); + const tokenTransferAmount = generateRandomIntNumberFrom1To100(); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + tokenTransferAmount + ); + const proposalAddress = await proposal.getAddress(); + + await waitForProposalToEnd(proposal); + + LOGGER.info('2. Verify proposal is passed and not executed'); + await checkProposalIsPassed(proposal, true); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance); + await expectTokenBalanceToEq(token, otherAccount.address, 0); + + LOGGER.info('4. Execute proposal'); + await proposal.executeProposal(); + + LOGGER.info('5. Verify proposal is executed'); + await checkProposalIsExecuted(proposal, true); + + LOGGER.info('6. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance - Number(tokenTransferAmount)); + await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); + + LOGGER.info('7. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + + LOGGER.info('8. Claim rewards by all accounts'); + await proposal.claimReward(); + + LOGGER.info('9. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + + LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); + expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); + + LOGGER.info('11. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); + + // this test covers correctness of NFT asset type DAO transfer tx + it('should pass with 1:0 (only creator vote) - NFT transfer from DAO', async function () { + const {dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const nftToken = await deployNftToken(); + const nftTokenAddress = await nftToken.getAddress(); + const daoAddress = await dao.getAddress(); + await (nftToken as ERC721Development).createNFT(daoAddress, ''); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendNftProposal( + dao, + nftTokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + 1 + ); + const proposalAddress = await proposal.getAddress(); + + await waitForProposalToEnd(proposal); + + LOGGER.info('2. Verify proposal is passed and not executed'); + await checkProposalIsPassed(proposal, true); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); + expect(await nftToken.balanceOf(daoAddress)).to.eq(1); + expect(await nftToken.balanceOf(otherAccount.address)).to.eq(0); + + LOGGER.info('4. Execute proposal'); + await proposal.executeProposal(); + + LOGGER.info('5. Verify proposal is executed'); + await checkProposalIsExecuted(proposal, true); + + LOGGER.info('6. Verify accounts NFT token balances after executing proposal: DAO lost 1 NFT, other account has 1 new NFT'); + expect(await nftToken.balanceOf(daoAddress)).to.eq(0); + expect(await nftToken.balanceOf(otherAccount.address)).to.eq(1); + + LOGGER.info('7. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + + LOGGER.info('8. Claim rewards by all accounts'); + await proposal.claimReward(); + + LOGGER.info('9. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + + LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); + expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); + + LOGGER.info('11. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); + + // this test covers correctness of ETH asset type DAO transfer tx + it('should pass with 1:0 (only creator vote) - ETH transfer from DAO', async function () { + const {dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const daoAddress = await dao.getAddress(); + // send 1 eth from account to dao + await account.sendTransaction({ + to: daoAddress, + value: ethers.parseEther('1') + }); + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendEthCryptoProposal( + dao, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + 0.3 + ); + const proposalAddress = await proposal.getAddress(); + + await waitForProposalToEnd(proposal); + + LOGGER.info('2. Verify proposal is passed and not executed'); + await checkProposalIsPassed(proposal, true); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('3. Verify accounts ERC20 token balances before executing proposal'); + expect(await ethers.provider.getBalance(daoAddress)).to.eq(ethers.parseEther('1')); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + + LOGGER.info('4. Execute proposal'); + await proposal.executeProposal(); + + LOGGER.info('5. Verify proposal is executed'); + await checkProposalIsExecuted(proposal, true); + + LOGGER.info('6. Verify ETH balances of DAO and other account after executing proposal: DAO has less ETH, other account has more ETH'); + expect(await ethers.provider.getBalance(daoAddress)).to.eq(ethers.parseEther('0.7')); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + expect(balanceOfOtherAccountAfter - balanceOfOtherAccountBefore).to.eq(ethers.parseEther('0.3')); + + LOGGER.info('7. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + + LOGGER.info('8. Claim rewards by all accounts'); + await proposal.claimReward(); + + LOGGER.info('9. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + + LOGGER.info('10. Expected creator balance: 1 ETH collateral back (no reward)'); + expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1); + + LOGGER.info('11. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }) + + + it('should pass with 3:2 (3 votes for)', async function () { + const {token, dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const daoAddress = await dao.getAddress(); + const signers = await ethers.getSigners(); + const otherAccount2 = signers[2]; + const otherAccount3 = signers[3]; + const otherAccount4 = signers[4]; + + const tokenTransferAmount = generateRandomIntNumberFrom1To100(); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + tokenTransferAmount + ); + const proposalAddress = await proposal.getAddress(); + + LOGGER.info('2. Vote 2 votes for (including initial creator vote it will be 3) and 2 votes against'); + const proposalByOtherAccount = proposal.connect(otherAccount); + const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, true, 1); + + const proposalByOtherAccount2 = proposal.connect(otherAccount2); + const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, true, 1); + + const proposalByOtherAccount3 = proposal.connect(otherAccount3); + const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); + + const proposalByOtherAccount4 = proposal.connect(otherAccount4); + const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); + + await Promise.all([res1, res2, res3, res4]); + + await waitForProposalToEnd(proposal); + + LOGGER.info('3. Verify proposal is passed and not executed'); + await checkProposalIsPassed(proposal, true); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('4. Verify accounts ERC20 token balances before executing proposal'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance); + await expectTokenBalanceToEq(token, otherAccount.address, 0); + + LOGGER.info('5. Execute proposal'); + await proposal.executeProposal(); + + LOGGER.info('6. Verify proposal is executed'); + await checkProposalIsExecuted(proposal, true); + + LOGGER.info('7. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance - Number(tokenTransferAmount)); + await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); + + LOGGER.info('8. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info('9. Claim rewards by all accounts (voters against should revert)'); + await proposal.claimReward(); + await proposalByOtherAccount.claimReward(); + await proposalByOtherAccount2.claimReward(); + await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); + + LOGGER.info('10. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); + + // 11. Expected for voting accounts: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH + LOGGER.info( + '11. Expected for voters balance: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH. Against voters should get 0 and pay claim tx fee' + ); + expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1.66); + expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 1.66); + expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 1.66); + expectBalanceNotChanged(balanceOfOtherAccount3Before, balanceOfOtherAccount3After); + expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); + + LOGGER.info('12. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); }); - it('should not pass when 2:3 (3 votes against)', async function () { - const { token, dao, account, otherAccount } = await loadFixture(initializeErc20TokenAndDaoFixture); - - const signers = await ethers.getSigners(); - const otherAccount2 = signers[2]; - const otherAccount3 = signers[3]; - const otherAccount4 = signers[4]; - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - generateRandomIntNumberFrom1To100() - ); - - LOGGER.info('2. Vote 3 votes against and 1 for'); - const proposalByOtherAccount = proposal.connect(otherAccount); - const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, false, 1); - - const proposalByOtherAccount2 = proposal.connect(otherAccount2); - const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, false, 1); - - const proposalByOtherAccount3 = proposal.connect(otherAccount3); - const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); - - const proposalByOtherAccount4 = proposal.connect(otherAccount4); - const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, true, 1); - - await Promise.all([res1, res2, res3, res4]); - - await waitForProposalToEnd(proposal); - - LOGGER.info('3. Execute proposal'); - await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); - - LOGGER.info('4. Verify proposal is not passed and not executed'); - await checkProposalIsPassed(proposal, false); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('5. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info('6. Claim rewards by all accounts'); - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await proposalByOtherAccount.claimReward(); - await proposalByOtherAccount2.claimReward(); - await proposalByOtherAccount3.claimReward(); - await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); - - LOGGER.info('7. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info( - '8. Expected against voters balance: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66 ETH. For voters should get 0 and pay claim tx fee' - ); - expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 1.66); - expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 1.66); - expectBalanceDiffIsGte(balanceOfOtherAccount3Before, balanceOfOtherAccount3After, 1.66); - expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); - expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); - - LOGGER.info('9. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); + describe('Proposal not pass scenarios', function () { + it('should not pass when 1:1 (creator vote and vote against)', async function () { + const {token, dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + + LOGGER.info('2. Other account votes against'); + const proposalByOtherAccount: Proposal = proposal.connect(otherAccount) as Proposal; + await voteOnProposalWithCollateral(proposalByOtherAccount, false, 1); + + await waitForProposalToEnd(proposal); + + LOGGER.info('3. Execute proposal should fail'); + await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); + + LOGGER.info('4. Verify proposal is not passed and not executed'); + await checkProposalIsPassed(proposal, false); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('5. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + + LOGGER.info('6. Claim rewards by all accounts'); + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await proposalByOtherAccount.claimReward(); + + LOGGER.info('7. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + + LOGGER.info('8. Expected voter against balance: 1 ETH collateral back + 1 ETH reward = 2 ETH. Creator should get 0 and pay claim tx fee'); + expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); + expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 2); + + LOGGER.info('9. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); + + it('should not pass when 2:3 (3 votes against)', async function () { + const {token, dao, account, otherAccount} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + + const signers = await ethers.getSigners(); + const otherAccount2 = signers[2]; + const otherAccount3 = signers[3]; + const otherAccount4 = signers[4]; + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + generateRandomIntNumberFrom1To100() + ); + const proposalAddress = await proposal.getAddress(); + + LOGGER.info('2. Vote 3 votes against and 1 for'); + const proposalByOtherAccount = proposal.connect(otherAccount); + const res1 = voteOnProposalWithCollateral(proposalByOtherAccount, false, 1); + + const proposalByOtherAccount2 = proposal.connect(otherAccount2); + const res2 = voteOnProposalWithCollateral(proposalByOtherAccount2, false, 1); + + const proposalByOtherAccount3 = proposal.connect(otherAccount3); + const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); + + const proposalByOtherAccount4 = proposal.connect(otherAccount4); + const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, true, 1); + + await Promise.all([res1, res2, res3, res4]); + + await waitForProposalToEnd(proposal); + + LOGGER.info('3. Execute proposal'); + await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); + + LOGGER.info('4. Verify proposal is not passed and not executed'); + await checkProposalIsPassed(proposal, false); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('5. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info('6. Claim rewards by all accounts'); + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await proposalByOtherAccount.claimReward(); + await proposalByOtherAccount2.claimReward(); + await proposalByOtherAccount3.claimReward(); + await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); + + LOGGER.info('7. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info( + '8. Expected against voters balance: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66 ETH. For voters should get 0 and pay claim tx fee' + ); + expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 1.66); + expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 1.66); + expectBalanceDiffIsGte(balanceOfOtherAccount3Before, balanceOfOtherAccount3After, 1.66); + expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); + expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); + + LOGGER.info('9. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); }); - }); }); diff --git a/test/ProposalTokenVotesScenarios.spec.ts b/test/ProposalTokenVotesScenarios.spec.ts index 76ada9a..e03d3a9 100644 --- a/test/ProposalTokenVotesScenarios.spec.ts +++ b/test/ProposalTokenVotesScenarios.spec.ts @@ -1,23 +1,23 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { ethers, network } from 'hardhat'; import { - approveErc20, - expectBalanceDiffIsGte, - expectBalanceNotChanged, - expectTokenBalanceToEq, - generateRandomIntNumberFrom1To100, - generateRandomMerkleRoot, - generateRandomProposalId, - initializeErc20TokenAndDaoFixture, - transferERC20TokensToAddress, - waitForProposalToEnd, + approveErc20, + expectBalanceDiffIsGte, + expectBalanceNotChanged, + expectTokenBalanceToEq, + generateRandomIntNumberFrom1To100, + generateRandomMerkleRoot, + generateRandomProposalId, + initializeErc20TokenAndDaoFixture, + transferERC20TokensToAddress, + waitForProposalToEnd, } from './utils/utils'; import { - checkProposalIsExecuted, - checkProposalIsPassed, - createSendErc20Proposal, - voteOnProposalWithCollateral, - voteOnProposalWithTokenCollateral, + checkProposalIsExecuted, + checkProposalIsPassed, + createSendErc20Proposal, + voteOnProposalWithCollateral, + voteOnProposalWithTokenCollateral, } from './utils/proposal-utils'; import { LOGGER } from './utils/pino-logger-service'; import { depositTokensToPool } from './utils/dao-pool-utils'; @@ -27,218 +27,224 @@ import { expect } from 'chai'; network.provider.send('evm_setIntervalMining', [500]); describe('Proposal with DAO governance token collateral votes scenarios', function () { - const daoTokensBalance = 1000; - - describe('Proposal passed scenarios', function () { - it('should pass with 3:2 (3 votes for with token collateral, 2 votes against with ETH collateral)', async function () { - const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); - - const signers = await ethers.getSigners(); - const otherAccount2 = signers[2]; - const otherAccount3 = signers[3]; - const otherAccount4 = signers[4]; - - const tokenTransferAmount = generateRandomIntNumberFrom1To100(); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - tokenTransferAmount - ); - - LOGGER.info('2. Send 100 ERC20 tokens to other account and other account 2'); - const transferRes = transferERC20TokensToAddress(token, otherAccount.address, 100); - const transferRes2 = transferERC20TokensToAddress(token, otherAccount2.address, 100); - await Promise.all([transferRes, transferRes2]); - - LOGGER.info('3. Approve ERC20Pool to spend 100 tokens of other account and other account 2'); - const tokenByOtherAccount = token.connect(otherAccount); - const approveRes = approveErc20(tokenByOtherAccount, ERC20DaoPool.address, 100); - const tokenByOtherAccount2 = token.connect(otherAccount2); - const approveRes2 = approveErc20(tokenByOtherAccount2, ERC20DaoPool.address, 100); - await Promise.all([approveRes, approveRes2]); - - LOGGER.info('4. Deposit 100 tokens to DAO pool by other account and other account 2'); - const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); - const depositRes = depositTokensToPool(daoPoolByOtherAccount, 100); - const daoPoolByOtherAccount2 = ERC20DaoPool.connect(otherAccount2); - const depositRes2 = depositTokensToPool(daoPoolByOtherAccount2, 100); - await Promise.all([depositRes, depositRes2]); - - LOGGER.info('4. Vote 2 votes for with token collateral (including initial creator vote it will be 3) and 2 votes against with ETH collateral'); - const proposalByOtherAccount = proposal.connect(otherAccount); - const res1 = voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); - - const proposalByOtherAccount2 = proposal.connect(otherAccount2); - const res2 = voteOnProposalWithTokenCollateral(proposalByOtherAccount2, true); - - const proposalByOtherAccount3 = proposal.connect(otherAccount3); - const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); - - const proposalByOtherAccount4 = proposal.connect(otherAccount4); - const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); - - await Promise.all([res1, res2, res3, res4]); - - await waitForProposalToEnd(proposal); - - LOGGER.info('5. Verify proposal is passed and not executed'); - await checkProposalIsPassed(proposal, true); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('6. Verify accounts ERC20 token balances before executing proposal'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance); - await expectTokenBalanceToEq(token, otherAccount.address, 0); - - LOGGER.info('7. Execute proposal'); - await proposal.executeProposal(); - - LOGGER.info('8. Verify proposal is executed'); - await checkProposalIsExecuted(proposal, true); - - LOGGER.info('9. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); - await expectTokenBalanceToEq(token, dao.address, daoTokensBalance - Number(tokenTransferAmount)); - await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); - - LOGGER.info('10. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info('11. Claim rewards by all accounts (voters against should revert)'); - await proposal.claimReward(); - await proposalByOtherAccount.claimReward(); - await proposalByOtherAccount2.claimReward(); - await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); - await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); - - LOGGER.info('12. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); - - // 11. Expected for voting accounts: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH - LOGGER.info( - '13. Expected for voters balance: 1/3 of 2 ETH = ~0.66666 ETH, creator gets 1 ETH collateral extra. Against voters should get 0 and pay claim tx fee' - ); - expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1.66); - expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 0.66); - expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 0.66); - expectBalanceNotChanged(balanceOfOtherAccount3Before, balanceOfOtherAccount3After); - expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); - - LOGGER.info('14. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); + const daoTokensBalance = 1000; + + describe('Proposal passed scenarios', function () { + it('should pass with 3:2 (3 votes for with token collateral, 2 votes against with ETH collateral)', async function () { + const {token, dao, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const erc20DaoPoolAddress = await ERC20DaoPool.getAddress(); + const daoAddress = await dao.getAddress(); + const signers = await ethers.getSigners(); + const otherAccount2 = signers[2]; + const otherAccount3 = signers[3]; + const otherAccount4 = signers[4]; + + const tokenTransferAmount = generateRandomIntNumberFrom1To100(); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + tokenTransferAmount + ); + const proposalAddress = await proposal.getAddress(); + + LOGGER.info('2. Send 100 ERC20 tokens to other account and other account 2'); + const transferRes = transferERC20TokensToAddress(token, otherAccount.address, 100); + const transferRes2 = transferERC20TokensToAddress(token, otherAccount2.address, 100); + await Promise.all([transferRes, transferRes2]); + + LOGGER.info('3. Approve ERC20Pool to spend 100 tokens of other account and other account 2'); + const tokenByOtherAccount = token.connect(otherAccount); + const approveRes = approveErc20(tokenByOtherAccount, erc20DaoPoolAddress, 100); + const tokenByOtherAccount2 = token.connect(otherAccount2); + const approveRes2 = approveErc20(tokenByOtherAccount2, erc20DaoPoolAddress, 100); + await Promise.all([approveRes, approveRes2]); + + LOGGER.info('4. Deposit 100 tokens to DAO pool by other account and other account 2'); + const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); + const depositRes = depositTokensToPool(daoPoolByOtherAccount, 100); + const daoPoolByOtherAccount2 = ERC20DaoPool.connect(otherAccount2); + const depositRes2 = depositTokensToPool(daoPoolByOtherAccount2, 100); + await Promise.all([depositRes, depositRes2]); + + LOGGER.info('4. Vote 2 votes for with token collateral (including initial creator vote it will be 3) and 2 votes against with ETH collateral'); + const proposalByOtherAccount = proposal.connect(otherAccount); + const res1 = voteOnProposalWithTokenCollateral(proposalByOtherAccount, true); + + const proposalByOtherAccount2 = proposal.connect(otherAccount2); + const res2 = voteOnProposalWithTokenCollateral(proposalByOtherAccount2, true); + + const proposalByOtherAccount3 = proposal.connect(otherAccount3); + const res3 = await voteOnProposalWithCollateral(proposalByOtherAccount3, false, 1); + + const proposalByOtherAccount4 = proposal.connect(otherAccount4); + const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, false, 1); + + await Promise.all([res1, res2, res3, res4]); + + await waitForProposalToEnd(proposal); + + LOGGER.info('5. Verify proposal is passed and not executed'); + await checkProposalIsPassed(proposal, true); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('6. Verify accounts ERC20 token balances before executing proposal'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance); + await expectTokenBalanceToEq(token, otherAccount.address, 0); + + LOGGER.info('7. Execute proposal'); + await proposal.executeProposal(); + + LOGGER.info('8. Verify proposal is executed'); + await checkProposalIsExecuted(proposal, true); + + LOGGER.info('9. Verify accounts ERC20 token balances after executing proposal: DAO has less tokens, other account has more tokens'); + await expectTokenBalanceToEq(token, daoAddress, daoTokensBalance - Number(tokenTransferAmount)); + await expectTokenBalanceToEq(token, otherAccount.address, Number(tokenTransferAmount)); + + LOGGER.info('10. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info('11. Claim rewards by all accounts (voters against should revert)'); + await proposal.claimReward(); + await proposalByOtherAccount.claimReward(); + await proposalByOtherAccount2.claimReward(); + await expect(proposalByOtherAccount3.claimReward()).to.be.revertedWith('Reward not apply'); + await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); + + LOGGER.info('12. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); + + // 11. Expected for voting accounts: 1 ETH collateral back + 1/3 of 2 ETH back = ~1.66666 ETH + LOGGER.info( + '13. Expected for voters balance: 1/3 of 2 ETH = ~0.66666 ETH, creator gets 1 ETH collateral extra. Against voters should get 0 and pay claim tx fee' + ); + expectBalanceDiffIsGte(balanceOfAccountBefore, balanceOfAccountAfter, 1.66); + expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 0.66); + expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 0.66); + expectBalanceNotChanged(balanceOfOtherAccount3Before, balanceOfOtherAccount3After); + expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); + + LOGGER.info('14. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); + + it('should not pass with 2:3 (2 votes for with ETH collateral, 3 votes against with token collateral)', async function () { + const {token, dao, account, otherAccount, ERC20DaoPool} = await loadFixture(initializeErc20TokenAndDaoFixture); + const tokenAddress = await token.getAddress(); + const erc20DaoPoolAddress = await ERC20DaoPool.getAddress(); + + const signers = await ethers.getSigners(); + const otherAccount2 = signers[2]; + const otherAccount3 = signers[3]; + const otherAccount4 = signers[4]; + + const tokenTransferAmount = generateRandomIntNumberFrom1To100(); + + LOGGER.info('1. Create send ERC20 tokens proposal'); + const proposal = await createSendErc20Proposal( + dao, + tokenAddress, + generateRandomProposalId(), + generateRandomMerkleRoot(), + otherAccount.address, + tokenTransferAmount + ); + const proposalAddress = await proposal.getAddress(); + + LOGGER.info('2. Send 100 ERC20 tokens to other account and other account 2'); + const transferRes = transferERC20TokensToAddress(token, otherAccount.address, 100); + const transferRes2 = transferERC20TokensToAddress(token, otherAccount2.address, 100); + const transferRes3 = transferERC20TokensToAddress(token, otherAccount3.address, 100); + await Promise.all([transferRes, transferRes2, transferRes3]); + + LOGGER.info('3. Approve ERC20Pool to spend 100 tokens of other account and other account 2'); + const tokenByOtherAccount = token.connect(otherAccount); + const approveRes = approveErc20(tokenByOtherAccount, erc20DaoPoolAddress, 100); + const tokenByOtherAccount2 = token.connect(otherAccount2); + const approveRes2 = approveErc20(tokenByOtherAccount2, erc20DaoPoolAddress, 100); + const tokenByOtherAccount3 = token.connect(otherAccount3); + const approveRes3 = approveErc20(tokenByOtherAccount3, erc20DaoPoolAddress, 100); + await Promise.all([approveRes, approveRes2, approveRes3]); + + LOGGER.info('4. Deposit 100 tokens to DAO pool by other account and other account 2 and other account 3'); + const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); + const depositRes = depositTokensToPool(daoPoolByOtherAccount, 100); + const daoPoolByOtherAccount2 = ERC20DaoPool.connect(otherAccount2); + const depositRes2 = depositTokensToPool(daoPoolByOtherAccount2, 100); + const daoPoolByOtherAccount3 = ERC20DaoPool.connect(otherAccount3); + const depositRes3 = depositTokensToPool(daoPoolByOtherAccount3, 100); + await Promise.all([depositRes, depositRes2, depositRes3]); + + LOGGER.info('5. Vote 1 votes for with ETH collateral (including initial creator vote it will be 2) and 3 votes against with token collateral'); + const proposalByOtherAccount = proposal.connect(otherAccount); + const res1 = voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); + + const proposalByOtherAccount2 = proposal.connect(otherAccount2); + const res2 = voteOnProposalWithTokenCollateral(proposalByOtherAccount2, false); + + const proposalByOtherAccount3 = proposal.connect(otherAccount3); + const res3 = voteOnProposalWithTokenCollateral(proposalByOtherAccount3, false); + + const proposalByOtherAccount4 = proposal.connect(otherAccount4); + const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, true, 1); + + await Promise.all([res1, res2, res3, res4]); + + await waitForProposalToEnd(proposal); + + LOGGER.info('6. Verify proposal is not passed and not executed'); + await checkProposalIsPassed(proposal, false); + await checkProposalIsExecuted(proposal, false); + + LOGGER.info('7. Execute proposal'); + await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); + + LOGGER.info('8. Get accounts balances before claiming reward'); + const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info('9. Claim rewards by all accounts (voters against should revert)'); + await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); + await proposalByOtherAccount.claimReward(); + await proposalByOtherAccount2.claimReward(); + await proposalByOtherAccount3.claimReward(); + await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); + + LOGGER.info('10. Get accounts balances after claiming reward'); + const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); + const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); + const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); + const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); + const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); + + LOGGER.info('11. Expected against voters balance: 1/3 of 2 ETH = ~0.66666 ETH. For voters should get 0 and pay claim tx fee'); + expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); + expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 0.66); + expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 0.66); + expectBalanceDiffIsGte(balanceOfOtherAccount3Before, balanceOfOtherAccount3After, 0.66); + expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); + + LOGGER.info('12. Expected proposal balance is 0'); + const balanceOfProposal = await ethers.provider.getBalance(proposalAddress); + expect(balanceOfProposal).to.be.eq(0); + }); }); - - it('should not pass with 2:3 (2 votes for with ETH collateral, 3 votes against with token collateral)', async function () { - const { token, dao, account, otherAccount, ERC20DaoPool } = await loadFixture(initializeErc20TokenAndDaoFixture); - - const signers = await ethers.getSigners(); - const otherAccount2 = signers[2]; - const otherAccount3 = signers[3]; - const otherAccount4 = signers[4]; - - const tokenTransferAmount = generateRandomIntNumberFrom1To100(); - - LOGGER.info('1. Create send ERC20 tokens proposal'); - const proposal = await createSendErc20Proposal( - dao, - token.address, - generateRandomProposalId(), - generateRandomMerkleRoot(), - otherAccount.address, - tokenTransferAmount - ); - - LOGGER.info('2. Send 100 ERC20 tokens to other account and other account 2'); - const transferRes = transferERC20TokensToAddress(token, otherAccount.address, 100); - const transferRes2 = transferERC20TokensToAddress(token, otherAccount2.address, 100); - const transferRes3 = transferERC20TokensToAddress(token, otherAccount3.address, 100); - await Promise.all([transferRes, transferRes2, transferRes3]); - - LOGGER.info('3. Approve ERC20Pool to spend 100 tokens of other account and other account 2'); - const tokenByOtherAccount = token.connect(otherAccount); - const approveRes = approveErc20(tokenByOtherAccount, ERC20DaoPool.address, 100); - const tokenByOtherAccount2 = token.connect(otherAccount2); - const approveRes2 = approveErc20(tokenByOtherAccount2, ERC20DaoPool.address, 100); - const tokenByOtherAccount3 = token.connect(otherAccount3); - const approveRes3 = approveErc20(tokenByOtherAccount3, ERC20DaoPool.address, 100); - await Promise.all([approveRes, approveRes2, approveRes3]); - - LOGGER.info('4. Deposit 100 tokens to DAO pool by other account and other account 2 and other account 3'); - const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); - const depositRes = depositTokensToPool(daoPoolByOtherAccount, 100); - const daoPoolByOtherAccount2 = ERC20DaoPool.connect(otherAccount2); - const depositRes2 = depositTokensToPool(daoPoolByOtherAccount2, 100); - const daoPoolByOtherAccount3 = ERC20DaoPool.connect(otherAccount3); - const depositRes3 = depositTokensToPool(daoPoolByOtherAccount3, 100); - await Promise.all([depositRes, depositRes2, depositRes3]); - - LOGGER.info('5. Vote 1 votes for with ETH collateral (including initial creator vote it will be 2) and 3 votes against with token collateral'); - const proposalByOtherAccount = proposal.connect(otherAccount); - const res1 = voteOnProposalWithTokenCollateral(proposalByOtherAccount, false); - - const proposalByOtherAccount2 = proposal.connect(otherAccount2); - const res2 = voteOnProposalWithTokenCollateral(proposalByOtherAccount2, false); - - const proposalByOtherAccount3 = proposal.connect(otherAccount3); - const res3 = voteOnProposalWithTokenCollateral(proposalByOtherAccount3, false); - - const proposalByOtherAccount4 = proposal.connect(otherAccount4); - const res4 = voteOnProposalWithCollateral(proposalByOtherAccount4, true, 1); - - await Promise.all([res1, res2, res3, res4]); - - await waitForProposalToEnd(proposal); - - LOGGER.info('6. Verify proposal is not passed and not executed'); - await checkProposalIsPassed(proposal, false); - await checkProposalIsExecuted(proposal, false); - - LOGGER.info('7. Execute proposal'); - await expect(proposal.executeProposal()).to.be.revertedWith('Proposal did not pass'); - - LOGGER.info('8. Get accounts balances before claiming reward'); - const balanceOfAccountBefore = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountBefore = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2Before = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3Before = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4Before = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info('9. Claim rewards by all accounts (voters against should revert)'); - await expect(proposal.claimReward()).to.be.revertedWith('Reward not apply'); - await proposalByOtherAccount.claimReward(); - await proposalByOtherAccount2.claimReward(); - await proposalByOtherAccount3.claimReward(); - await expect(proposalByOtherAccount4.claimReward()).to.be.revertedWith('Reward not apply'); - - LOGGER.info('10. Get accounts balances after claiming reward'); - const balanceOfAccountAfter = await ethers.provider.getBalance(account.address); - const balanceOfOtherAccountAfter = await ethers.provider.getBalance(otherAccount.address); - const balanceOfOtherAccount2After = await ethers.provider.getBalance(otherAccount2.address); - const balanceOfOtherAccount3After = await ethers.provider.getBalance(otherAccount3.address); - const balanceOfOtherAccount4After = await ethers.provider.getBalance(otherAccount4.address); - - LOGGER.info('11. Expected against voters balance: 1/3 of 2 ETH = ~0.66666 ETH. For voters should get 0 and pay claim tx fee'); - expectBalanceNotChanged(balanceOfAccountBefore, balanceOfAccountAfter); - expectBalanceDiffIsGte(balanceOfOtherAccountBefore, balanceOfOtherAccountAfter, 0.66); - expectBalanceDiffIsGte(balanceOfOtherAccount2Before, balanceOfOtherAccount2After, 0.66); - expectBalanceDiffIsGte(balanceOfOtherAccount3Before, balanceOfOtherAccount3After, 0.66); - expectBalanceNotChanged(balanceOfOtherAccount4Before, balanceOfOtherAccount4After); - - LOGGER.info('12. Expected proposal balance is 0'); - const balanceOfProposal = await ethers.provider.getBalance(proposal.address); - expect(balanceOfProposal).to.be.eq(0); - }); - }); }); diff --git a/test/test-constants.ts b/test/test-constants.ts index 74f1c7a..7b43309 100644 --- a/test/test-constants.ts +++ b/test/test-constants.ts @@ -2,6 +2,6 @@ import { ethers } from 'ethers'; export const ERC_20_DECIMALS = 18; export const CHALLENGE_PERIOD_SECONDS = 15; -export const NATIVE_COLLATERAL = ethers.utils.parseEther('1'); -export const TOKEN_COLLATERAL = ethers.utils.parseUnits('100', ERC_20_DECIMALS); +export const NATIVE_COLLATERAL = ethers.parseEther('1'); +export const TOKEN_COLLATERAL = ethers.parseUnits('100', ERC_20_DECIMALS); export const TOKEN_NFT_COLLATERAL = 1; diff --git a/test/utils/dao-pool-utils.ts b/test/utils/dao-pool-utils.ts index 5950bfe..0de9d39 100644 --- a/test/utils/dao-pool-utils.ts +++ b/test/utils/dao-pool-utils.ts @@ -5,13 +5,13 @@ import { ERC_20_DECIMALS } from '../test-constants'; export const depositTokensToPool = async (pool: ERC20DaoPool, amount: number) => { LOGGER.debug(`Depositing tokens ${amount} ERC20 tokens to DAO pool`); - await pool.deposit(ethers.utils.parseUnits(amount.toFixed(0), ERC_20_DECIMALS)); + await pool.deposit(ethers.parseUnits(amount.toFixed(0), ERC_20_DECIMALS)); }; export const createErc20DaoPool = async (token: IERC20): Promise => { - return (await ethers.deployContract('ERC20DaoPool', [token.address])) as ERC20DaoPool; + return (await ethers.deployContract('ERC20DaoPool', [token.getAddress()])) as ERC20DaoPool; }; export const createNftDaoPool = async (token: ERC721): Promise => { - return (await ethers.deployContract('NFTDaoPool', [token.address])) as NFTDaoPool; + return (await ethers.deployContract('NFTDaoPool', [token.getAddress()])) as NFTDaoPool; }; diff --git a/test/utils/proposal-utils.ts b/test/utils/proposal-utils.ts index 51fed4f..fef7079 100644 --- a/test/utils/proposal-utils.ts +++ b/test/utils/proposal-utils.ts @@ -3,7 +3,6 @@ import { LOGGER } from './pino-logger-service'; import { expect } from 'chai'; import { Dao, Proposal } from '../../typechain-types'; import { ERC_20_DECIMALS } from '../test-constants'; -import { parseEther } from 'ethers/lib/utils'; export async function createSendErc20Proposal( dao: Dao, @@ -51,13 +50,14 @@ export async function createProposalWithTokensTx( ethCollateralToSendToProposal: string = '1' ): Promise { const tx = await dao.createProposal(proposalId, merkleRootHex, [sendDaoTokensTx], { - value: ethers.utils.parseEther(ethCollateralToSendToProposal), + value: ethers.parseEther(ethCollateralToSendToProposal), }); // @dev there was a problem with .on listener and it didn't work for multiple tests // @dev so i replaced it with this workaround of getting events from tx const result = await tx.wait(); LOGGER.debug(`Created DAO proposal`); - return (await ethers.getContractAt('Proposal', result.events[0].args.proposalAddress)) as Proposal; + // @ts-ignore + return (await ethers.getContractAt('Proposal', result.logs[0].args.proposalAddress)) as Proposal; } @@ -72,7 +72,7 @@ export const encodeSendErc20TokensTx = ( proposalId, tokenAddress, tokenReceiverAddress, - ethers.utils.parseUnits(tokenTransferAmount, ERC_20_DECIMALS), + ethers.parseUnits(tokenTransferAmount, ERC_20_DECIMALS), ]); }; @@ -100,7 +100,7 @@ export const encodeSendCryptoTx = ( return dao.interface.encodeFunctionData('sendCrypto', [ proposalId, tokenReceiverAddress, - parseEther(ethAmount.toString()), + ethers.parseEther(ethAmount.toString()), ]); }; @@ -119,7 +119,7 @@ export const checkProposalIsExecuted = async (proposal: Proposal, expectedResult export const voteOnProposalWithCollateral = async (proposal: Proposal, vote: boolean, ethCollateralInt: number): Promise => { LOGGER.debug(`Voting '${vote}' on proposal with collateral '${ethCollateralInt}'`); await proposal.vote(vote, { - value: ethers.utils.parseEther(ethCollateralInt.toFixed(0)), + value: ethers.parseEther(ethCollateralInt.toFixed(0)), }); }; diff --git a/test/utils/utils.ts b/test/utils/utils.ts index 9dd824f..1061306 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -1,4 +1,3 @@ -import { BigNumber } from 'ethers'; import { ethers } from 'hardhat'; import { expect } from 'chai'; import { faker } from '@faker-js/faker'; @@ -11,53 +10,55 @@ export async function deployErc20Token(): Promise { // DEPLOY TOKEN const name = faker.hacker.noun(); const symbol = faker.hacker.abbreviation(); - const totalSupply = ethers.utils.parseUnits('10000', ERC_20_DECIMALS); + const totalSupply = ethers.parseUnits('10000', ERC_20_DECIMALS); const token = await ethers.deployContract('ERC20Development', [name, symbol, totalSupply]); - await token.deployed(); - LOGGER.debug(`ERC20 token deployed to ${token.address}`); - return token as IERC20; + await token.waitForDeployment(); + const address = await token.getAddress(); + LOGGER.debug(`ERC20 token deployed to ${address}`); + return token as IERC20 } export async function deployNftToken(): Promise { // DEPLOY TOKEN const token = await ethers.deployContract('ERC721Development'); - await token.deployed(); - LOGGER.debug(`ERC721 token deployed to ${token.address}`); + await token.waitForDeployment(); + const address = await token.getAddress(); + LOGGER.debug(`ERC721 token deployed to ${address}`); return token as ERC721; } export async function deployErc20Dao(tokenAddress: string, challengePeriodSeconds: number): Promise<{ dao: ERC20Dao; ERC20DaoPool: ERC20DaoPool }> { const dao = (await ethers.deployContract('ERC20Dao', [tokenAddress, TOKEN_COLLATERAL, challengePeriodSeconds, NATIVE_COLLATERAL])) as ERC20Dao; - await dao.deployed(); - // @dev there was a problem with .on listener and it didn't work for multiple tests - const result = await dao.deployTransaction.wait(); + await dao.waitForDeployment(); + const result = await dao.deploymentTransaction().wait(); const ERC20DaoPool = (await ethers.getContractAt( 'ERC20DaoPool', // @ts-ignore - result.events[1].args.daoPoolAddress + result.logs[1].args.daoPoolAddress )) as ERC20DaoPool; - LOGGER.debug(`ERC20 DAO deployed to ${dao.address}`); + const address = await dao.getAddress(); + LOGGER.debug(`ERC20 DAO deployed to ${address}`); return { dao, ERC20DaoPool }; } export async function deployNftDao(tokenAddress: string, challengePeriodSeconds: number): Promise<{ dao: NFTDao; NFTDaoPool: NFTDaoPool }> { const dao = (await ethers.deployContract('NFTDao', [tokenAddress, TOKEN_NFT_COLLATERAL, challengePeriodSeconds, NATIVE_COLLATERAL])) as NFTDao; - await dao.deployed(); - // @dev there was a problem with .on listener and it didn't work for multiple tests - const result = await dao.deployTransaction.wait(); + await dao.waitForDeployment(); + const result = await dao.deploymentTransaction().wait(); const NFTDaoPool = (await ethers.getContractAt( 'NFTDaoPool', // @ts-ignore - result.events[1].args.daoPoolAddress + result.logs[1].args.daoPoolAddress )) as NFTDaoPool; - LOGGER.debug(`NFT DAO deployed to ${dao.address}`); + const address = await dao.getAddress(); + LOGGER.debug(`NFT DAO deployed to ${address}`); return { dao, NFTDaoPool }; } export async function transferERC20TokensToAddress(token: IERC20, receiver: string, tokenAmount: number): Promise { - await token.transfer(receiver, ethers.utils.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); + await token.transfer(receiver, ethers.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); const balanceOfDao = await token.balanceOf(receiver); - expect(balanceOfDao).to.be.eq(ethers.utils.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); + expect(balanceOfDao).to.be.eq(ethers.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); LOGGER.debug(`Sent ${tokenAmount} tokens to ${receiver}`); } @@ -66,8 +67,9 @@ export async function mintNft(token: ERC721Development, receiver: string): Promi } export async function approveErc20(token: IERC20, addressToApprove: string, tokenAmount: number): Promise { - await token.approve(addressToApprove, ethers.utils.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); - LOGGER.debug(`Approved ${addressToApprove} to spend ${tokenAmount} tokens of ${token.address}`); + await token.approve(addressToApprove, ethers.parseUnits(tokenAmount.toFixed(0), ERC_20_DECIMALS)); + const address = await token.getAddress(); + LOGGER.debug(`Approved ${addressToApprove} to spend ${tokenAmount} tokens of ${address}`); } export const generateRandomMerkleRoot = (): string => { @@ -75,7 +77,7 @@ export const generateRandomMerkleRoot = (): string => { }; export const generateRandomProposalId = (): Uint8Array => { - return ethers.utils.toUtf8Bytes(faker.string.uuid()); + return ethers.toUtf8Bytes(faker.string.uuid()); }; export const generateRandomIntNumberFrom1To100 = (): string => { @@ -99,15 +101,18 @@ export const waitForProposalToEnd = async (proposal: Proposal) => { /// DAO gets 1000 ERC20 governance tokens export async function initializeErc20TokenAndDaoFixture() { const token = await deployErc20Token(); - const { dao, ERC20DaoPool } = await deployErc20Dao(token.address, CHALLENGE_PERIOD_SECONDS); - await transferERC20TokensToAddress(token, dao.address, 1000); + const tokenAddress = await token.getAddress(); + const { dao, ERC20DaoPool } = await deployErc20Dao(tokenAddress, CHALLENGE_PERIOD_SECONDS); + const daoAddress = await dao.getAddress(); + await transferERC20TokensToAddress(token, daoAddress, 1000); const [account, otherAccount] = await ethers.getSigners(); return { token, dao, account, otherAccount, ERC20DaoPool }; } export async function initializeNftTokenAndDaoFixture() { const token = await deployNftToken(); - const { dao, NFTDaoPool } = await deployNftDao(token.address, CHALLENGE_PERIOD_SECONDS); + const tokenAddress = await token.getAddress(); + const { dao, NFTDaoPool } = await deployNftDao(tokenAddress, CHALLENGE_PERIOD_SECONDS); const [account, otherAccount] = await ethers.getSigners(); return { token, dao, account, otherAccount, NFTDaoPool }; } @@ -118,7 +123,8 @@ export async function initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens( await transferERC20TokensToAddress(token, otherAccount.address, 1000); const tokenByOtherAccount = token.connect(otherAccount); - await approveErc20(tokenByOtherAccount, ERC20DaoPool.address, 500); + const erc20DaoPoolAddress = await ERC20DaoPool.getAddress(); + await approveErc20(tokenByOtherAccount, erc20DaoPoolAddress, 500); const daoPoolByOtherAccount = ERC20DaoPool.connect(otherAccount); //500 tokens should be 5 votes because of 100 tokens per vote @@ -126,20 +132,20 @@ export async function initializeErc20TokenAndDaoAndOtherAccountWith500DaoTokens( return { token, dao, account, otherAccount, ERC20DaoPool }; } -export const expectBalanceDiffIsGte = (balanceBefore: BigNumber, balanceAfter: BigNumber, expectedDiff: number): void => { - expect(Number(Number(ethers.utils.formatEther(balanceAfter.sub(balanceBefore).toString())).toFixed(2))).to.be.gte(expectedDiff); +export const expectBalanceDiffIsGte = (balanceBefore: bigint, balanceAfter: bigint, expectedDiff: number): void => { + expect(Number(Number(ethers.formatEther(balanceAfter - balanceBefore)).toFixed(2))).to.be.gte(expectedDiff); }; // only tx cost included to balance diff -export const expectBalanceNotChanged = (balanceBefore: BigNumber, balanceAfter: BigNumber): void => { - expect(Number(Number(ethers.utils.formatEther(balanceAfter.sub(balanceBefore).toString())).toFixed(2))).to.be.lt(0.1); +export const expectBalanceNotChanged = (balanceBefore: bigint, balanceAfter: bigint): void => { + expect(Number(Number(ethers.formatEther(balanceAfter - balanceBefore)).toFixed(2))).to.be.lt(0.1); }; export const expectTokenBalanceToEq = async (token: IERC20, address: string, expectedBalance: number, tokenDecimals: number = 18): Promise => { const balance = await token.balanceOf(address); - expect(balance).to.be.eq(ethers.utils.parseUnits(expectedBalance.toString(), tokenDecimals)); + expect(balance).to.be.eq(ethers.parseUnits(expectedBalance.toString(), tokenDecimals)); }; export const parseTokensUnits = (amount: number) => { - return ethers.utils.parseUnits(amount.toFixed(0), ERC_20_DECIMALS); + return ethers.parseUnits(amount.toFixed(0), ERC_20_DECIMALS); }; diff --git a/tsconfig.json b/tsconfig.json index 5706776..f75c0a1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "skipLibCheck": true, "resolveJsonModule": true, "outDir": "dist", - "types": ["@nomiclabs/hardhat-ethers"] + "types": ["@nomiclabs/hardhat-ethers", "typechain-types"] }, "include": ["./**/*.ts"], "files": ["./hardhat.config.ts"]