From cf3c377f8a523da0f1949b0ccc4c5b5d3b9d7f44 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 13:20:10 +0200 Subject: [PATCH 01/17] migrate Ownable tests to ethers --- hardhat.config.js | 4 +- package-lock.json | 1086 +++++++++++++++++++++++++++++++++-- package.json | 6 +- test/access/Ownable.test.js | 82 +-- test/helpers/deploy.js | 20 + 5 files changed, 1110 insertions(+), 88 deletions(-) create mode 100644 test/helpers/deploy.js diff --git a/hardhat.config.js b/hardhat.config.js index 4d5ab944ada..9a7667a9f06 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -55,7 +55,9 @@ const argv = require('yargs/yargs')() }, }).argv; -require('@nomiclabs/hardhat-truffle5'); +// require('@nomiclabs/hardhat-truffle5'); +require('@nomicfoundation/hardhat-toolbox'); +require('@nomicfoundation/hardhat-ethers'); require('hardhat-ignore-warnings'); require('hardhat-exposed'); require('solidity-docgen'); diff --git a/package-lock.json b/package-lock.json index 0f4f9f55e4e..11586105968 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,11 @@ "@changesets/cli": "^2.26.0", "@changesets/pre": "^1.0.14", "@changesets/read": "^0.5.9", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", + "@nomicfoundation/hardhat-ethers": "^3.0.4", "@nomicfoundation/hardhat-foundry": "^1.1.1", "@nomicfoundation/hardhat-network-helpers": "^1.0.3", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/docs-utils": "^0.1.5", @@ -28,9 +31,10 @@ "eth-sig-util": "^3.0.0", "ethereumjs-util": "^7.0.7", "ethereumjs-wallet": "^1.0.1", + "ethers": "^6.7.1", "glob": "^10.3.5", "graphlib": "^2.1.8", - "hardhat": "^2.9.1", + "hardhat": "^2.17.4", "hardhat-exposed": "^0.3.13", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.0", @@ -63,6 +67,12 @@ "node": ">=0.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 + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -431,6 +441,19 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@ensdomains/address-encoder": { "version": "0.1.9", "resolved": "https://registry.npmjs.org/@ensdomains/address-encoder/-/address-encoder-0.1.9.tgz", @@ -1542,6 +1565,34 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@manypkg/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", @@ -2013,6 +2064,38 @@ "node": ">=14" } }, + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "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, + "dependencies": { + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "chai": "^4.2.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, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" + } + }, "node_modules/@nomicfoundation/hardhat-foundry": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-foundry/-/hardhat-foundry-1.1.1.tgz", @@ -2037,6 +2120,75 @@ "hardhat": "^2.9.5" } }, + "node_modules/@nomicfoundation/hardhat-toolbox": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz", + "integrity": "sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==", + "dev": true, + "peerDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-verify": "^1.0.0", + "@typechain/ethers-v6": "^0.4.0", + "@typechain/hardhat": "^8.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=12.0.0", + "chai": "^4.2.0", + "ethers": "^6.4.0", + "hardhat": "^2.11.0", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.2.0", + "typescript": ">=4.5.0" + } + }, + "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/hardhat-verify/node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", @@ -2274,6 +2426,64 @@ "web3-utils": "^1.2.1" } }, + "node_modules/@nomiclabs/truffle-contract/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/@nomiclabs/truffle-contract/node_modules/ethers": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", + "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@nomiclabs/truffle-contract/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@nomiclabs/truffle-contract/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true + }, + "node_modules/@nomiclabs/truffle-contract/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/@nomiclabs/truffle-contract/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "dev": true + }, + "node_modules/@nomiclabs/truffle-contract/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true + }, "node_modules/@openzeppelin/contract-loader": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/@openzeppelin/contract-loader/-/contract-loader-0.6.3.tgz", @@ -2968,6 +3178,12 @@ "node": "^16.20 || ^18.16 || >=20" } }, + "node_modules/@truffle/contract/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/@truffle/contract/node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", @@ -2988,6 +3204,58 @@ "xhr-request-promise": "^0.1.2" } }, + "node_modules/@truffle/contract/node_modules/ethers": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", + "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@truffle/contract/node_modules/ethers/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/@truffle/contract/node_modules/ethers/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true + }, + "node_modules/@truffle/contract/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/contract/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true + }, + "node_modules/@truffle/contract/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "dev": true + }, "node_modules/@truffle/contract/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -3358,6 +3626,12 @@ "node": "^16.20 || ^18.16 || >=20" } }, + "node_modules/@truffle/interface-adapter/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/@truffle/interface-adapter/node_modules/bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", @@ -3399,6 +3673,64 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/@truffle/interface-adapter/node_modules/ethers": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", + "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "dev": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/ethers/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/ethers/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/ethers/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/@truffle/interface-adapter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true + }, + "node_modules/@truffle/interface-adapter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "dev": true + }, "node_modules/@truffle/interface-adapter/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -3736,6 +4068,105 @@ "node": ">=4" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "peer": true + }, + "node_modules/@typechain/ethers-v6": { + "version": "0.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": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "ethers": "6.x", + "typechain": "^8.3.1", + "typescript": ">=4.7.0" + } + }, + "node_modules/@typechain/hardhat": { + "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": { + "@typechain/ethers-v6": "^0.4.3", + "ethers": "^6.1.0", + "hardhat": "^2.9.9", + "typechain": "^8.3.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" + } + }, "node_modules/@types/bignumber.js": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", @@ -3773,6 +4204,15 @@ "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==", "dev": true }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz", + "integrity": "sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/concat-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", @@ -3843,6 +4283,13 @@ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, + "node_modules/@types/mocha": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", + "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==", + "dev": true, + "peer": true + }, "node_modules/@types/node": { "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", @@ -3864,6 +4311,13 @@ "@types/node": "*" } }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true, + "peer": true + }, "node_modules/@types/qs": { "version": "6.9.8", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", @@ -3998,6 +4452,16 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/address": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", @@ -4158,6 +4622,13 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "peer": true + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -4167,6 +4638,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", @@ -4352,6 +4833,16 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -4942,6 +5433,18 @@ "node": ">=4" } }, + "node_modules/chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 5" + } + }, "node_modules/chai-bn": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.2.2.tgz", @@ -5319,6 +5822,58 @@ "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", "dev": true }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", @@ -5550,6 +6105,13 @@ "sha.js": "^2.4.8" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "peer": true + }, "node_modules/cross-fetch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", @@ -5797,6 +6359,16 @@ "node": ">=6" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7097,63 +7669,84 @@ } }, "node_modules/ethers": { - "version": "4.0.49", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", - "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "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://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.4", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" + "@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/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/ethers/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "node_modules/ethers/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, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/ethers/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", - "dev": true + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] }, - "node_modules/ethers/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "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 }, - "node_modules/ethers/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "node_modules/ethers/node_modules/aes-js": { + "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 }, - "node_modules/ethers/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, + "node_modules/ethers/node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/ethjs-abi": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/ethjs-abi/-/ethjs-abi-0.2.1.tgz", @@ -7523,6 +8116,19 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -8194,9 +8800,9 @@ } }, "node_modules/hardhat": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.17.3.tgz", - "integrity": "sha512-SFZoYVXW1bWJZrIIKXOA+IgcctfuKXDwENywiYNT2dM3YQc4fXNaTbuk/vpPzHIF50upByx4zW5EqczKYQubsA==", + "version": "2.17.4", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.17.4.tgz", + "integrity": "sha512-YTyHjVc9s14CY/O7Dbtzcr/92fcz6AzhrMaj6lYsZpYPIPLzOrFCZHHPxfGQB6FiE6IPNE0uJaAbr7zGF79goA==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -9865,12 +10471,32 @@ "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "peer": true + }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": 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 + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -10032,6 +10658,13 @@ "yallist": "^3.0.2" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "peer": true + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -11065,6 +11698,12 @@ "node": ">= 0.8.0" } }, + "node_modules/ordinal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", + "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", + "dev": true + }, "node_modules/os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -11911,6 +12550,16 @@ "node": ">=8" } }, + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", @@ -13993,6 +14642,13 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "dev": true, + "peer": true + }, "node_modules/string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -14353,6 +15009,42 @@ "node": ">=10.0.0" } }, + "node_modules/table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/table/node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -14597,6 +15289,162 @@ "node": ">=8" } }, + "node_modules/ts-command-line-args": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "string-format": "^2.0.0" + }, + "bin": { + "write-markdown": "dist/write-markdown.js" + } + }, + "node_modules/ts-command-line-args/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, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-command-line-args/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, + "peer": 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/ts-command-line-args/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, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-command-line-args/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, + "peer": true + }, + "node_modules/ts-command-line-args/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, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-command-line-args/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, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -14797,6 +15645,81 @@ "node": ">= 0.6" } }, + "node_modules/typechain": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.1.tgz", + "integrity": "sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prettier": "^2.1.1", + "debug": "^4.3.1", + "fs-extra": "^7.0.0", + "glob": "7.1.7", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.3.1", + "ts-command-line-args": "^2.2.0", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.3.0" + } + }, + "node_modules/typechain/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typechain/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typechain/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", @@ -14877,6 +15800,30 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -15033,6 +15980,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "peer": true + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -16082,6 +17036,30 @@ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, + "node_modules/wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "dev": true, + "peer": true, + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -16523,6 +17501,16 @@ "node": ">=12" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 55a89746e4e..e6d28bce06c 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,11 @@ "@changesets/cli": "^2.26.0", "@changesets/pre": "^1.0.14", "@changesets/read": "^0.5.9", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", + "@nomicfoundation/hardhat-ethers": "^3.0.4", "@nomicfoundation/hardhat-foundry": "^1.1.1", "@nomicfoundation/hardhat-network-helpers": "^1.0.3", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/docs-utils": "^0.1.5", @@ -68,9 +71,10 @@ "eth-sig-util": "^3.0.0", "ethereumjs-util": "^7.0.7", "ethereumjs-wallet": "^1.0.1", + "ethers": "^6.7.1", "glob": "^10.3.5", "graphlib": "^2.1.8", - "hardhat": "^2.9.1", + "hardhat": "^2.17.4", "hardhat-exposed": "^0.3.13", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.0", diff --git a/test/access/Ownable.test.js b/test/access/Ownable.test.js index f85daec5d28..36e3220c1ff 100644 --- a/test/access/Ownable.test.js +++ b/test/access/Ownable.test.js @@ -1,72 +1,80 @@ -const { constants, expectEvent } = require('@openzeppelin/test-helpers'); -const { expectRevertCustomError } = require('../helpers/customError'); - -const { ZERO_ADDRESS } = constants; - +const { ethers } = require('hardhat'); const { expect } = require('chai'); - -const Ownable = artifacts.require('$Ownable'); - -contract('Ownable', function (accounts) { - const [owner, other] = accounts; - +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { deploy, getFactory } = require('../helpers/deploy'); + +async function fixture() { + const accounts = await ethers.getSigners(); // this is slow :/ + const owner = accounts.shift(); + const other = accounts.shift(); + const ownable = await deploy('$Ownable', [ owner.address ]); + return { accounts, owner, other, ownable }; +}; + +describe('Ownable', function () { beforeEach(async function () { - this.ownable = await Ownable.new(owner); + await loadFixture(fixture).then(results => Object.assign(this, results)); }); it('rejects zero address for initialOwner', async function () { - await expectRevertCustomError(Ownable.new(constants.ZERO_ADDRESS), 'OwnableInvalidOwner', [constants.ZERO_ADDRESS]); + // checking a custom error requires a contract, or at least the interface + // we can get it from the contract factory + const { interface } = await getFactory('$Ownable'); + + await expect(deploy('$Ownable', [ ethers.ZeroAddress ])) + .to.be.revertedWithCustomError({ interface }, 'OwnableInvalidOwner') + .withArgs(ethers.ZeroAddress); }); it('has an owner', async function () { - expect(await this.ownable.owner()).to.equal(owner); + expect(await this.ownable.owner()).to.equal(this.owner.address); }); describe('transfer ownership', function () { it('changes owner after transfer', async function () { - const receipt = await this.ownable.transferOwnership(other, { from: owner }); - expectEvent(receipt, 'OwnershipTransferred'); + await expect(this.ownable.connect(this.owner).transferOwnership(this.other.address)) + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(this.owner.address, this.other.address); - expect(await this.ownable.owner()).to.equal(other); + expect(await this.ownable.owner()).to.equal(this.other.address); }); it('prevents non-owners from transferring', async function () { - await expectRevertCustomError( - this.ownable.transferOwnership(other, { from: other }), - 'OwnableUnauthorizedAccount', - [other], - ); + await expect(this.ownable.connect(this.other).transferOwnership(this.other.address)) + .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') + .withArgs(this.other.address); }); it('guards ownership against stuck state', async function () { - await expectRevertCustomError( - this.ownable.transferOwnership(ZERO_ADDRESS, { from: owner }), - 'OwnableInvalidOwner', - [ZERO_ADDRESS], - ); + await expect(this.ownable.connect(this.owner).transferOwnership(ethers.ZeroAddress)) + .to.be.revertedWithCustomError(this.ownable, 'OwnableInvalidOwner') + .withArgs(ethers.ZeroAddress); }); }); describe('renounce ownership', function () { it('loses ownership after renouncement', async function () { - const receipt = await this.ownable.renounceOwnership({ from: owner }); - expectEvent(receipt, 'OwnershipTransferred'); + await expect(this.ownable.connect(this.owner).renounceOwnership()) + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(this.owner.address, ethers.ZeroAddress); - expect(await this.ownable.owner()).to.equal(ZERO_ADDRESS); + expect(await this.ownable.owner()).to.equal(ethers.ZeroAddress); }); it('prevents non-owners from renouncement', async function () { - await expectRevertCustomError(this.ownable.renounceOwnership({ from: other }), 'OwnableUnauthorizedAccount', [ - other, - ]); + await expect(this.ownable.connect(this.other).renounceOwnership()) + .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') + .withArgs(this.other.address); }); it('allows to recover access using the internal _transferOwnership', async function () { - await this.ownable.renounceOwnership({ from: owner }); - const receipt = await this.ownable.$_transferOwnership(other); - expectEvent(receipt, 'OwnershipTransferred'); + await this.ownable.connect(this.owner).renounceOwnership(); + + await expect(this.ownable.$_transferOwnership(this.other.address)) + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(ethers.ZeroAddress, this.other.address); - expect(await this.ownable.owner()).to.equal(other); + expect(await this.ownable.owner()).to.equal(this.other.address); }); }); }); diff --git a/test/helpers/deploy.js b/test/helpers/deploy.js new file mode 100644 index 00000000000..763708ad298 --- /dev/null +++ b/test/helpers/deploy.js @@ -0,0 +1,20 @@ +const { ethers } = require('hardhat'); + +async function getFactory(name, opts = {}) { + return ethers.getContractFactory(name).then(contract => contract.connect(opts.signer || contract.runner)); +} + +function attach(name, address, opts = {}) { + return getFactory(name, opts).then(factory => factory.attach(address)); +} + +function deploy(name, args = [], opts = {}) { + if (!Array.isArray(args)) { opts = args; args = []; } + return getFactory(name, opts).then(factory => factory.deploy(...args)).then(contract => contract.waitForDeployment()); +} + +module.exports = { + getFactory, + attach, + deploy, +}; \ No newline at end of file From 673ff7984a2d88c861d07b73c342659f3dac7b27 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 13:43:04 +0200 Subject: [PATCH 02/17] fix lint --- test/access/Ownable.test.js | 38 ++++++++++++++++++------------------- test/helpers/deploy.js | 21 ++++++++++++-------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/test/access/Ownable.test.js b/test/access/Ownable.test.js index 36e3220c1ff..f9cfa0a9928 100644 --- a/test/access/Ownable.test.js +++ b/test/access/Ownable.test.js @@ -5,11 +5,11 @@ const { deploy, getFactory } = require('../helpers/deploy'); async function fixture() { const accounts = await ethers.getSigners(); // this is slow :/ - const owner = accounts.shift(); - const other = accounts.shift(); - const ownable = await deploy('$Ownable', [ owner.address ]); + const owner = accounts.shift(); + const other = accounts.shift(); + const ownable = await deploy('$Ownable', [owner.address]); return { accounts, owner, other, ownable }; -}; +} describe('Ownable', function () { beforeEach(async function () { @@ -21,9 +21,9 @@ describe('Ownable', function () { // we can get it from the contract factory const { interface } = await getFactory('$Ownable'); - await expect(deploy('$Ownable', [ ethers.ZeroAddress ])) - .to.be.revertedWithCustomError({ interface }, 'OwnableInvalidOwner') - .withArgs(ethers.ZeroAddress); + await expect(deploy('$Ownable', [ethers.ZeroAddress])) + .to.be.revertedWithCustomError({ interface }, 'OwnableInvalidOwner') + .withArgs(ethers.ZeroAddress); }); it('has an owner', async function () { @@ -33,46 +33,46 @@ describe('Ownable', function () { describe('transfer ownership', function () { it('changes owner after transfer', async function () { await expect(this.ownable.connect(this.owner).transferOwnership(this.other.address)) - .to.emit(this.ownable, 'OwnershipTransferred') - .withArgs(this.owner.address, this.other.address); + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(this.owner.address, this.other.address); expect(await this.ownable.owner()).to.equal(this.other.address); }); it('prevents non-owners from transferring', async function () { await expect(this.ownable.connect(this.other).transferOwnership(this.other.address)) - .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') - .withArgs(this.other.address); + .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') + .withArgs(this.other.address); }); it('guards ownership against stuck state', async function () { await expect(this.ownable.connect(this.owner).transferOwnership(ethers.ZeroAddress)) - .to.be.revertedWithCustomError(this.ownable, 'OwnableInvalidOwner') - .withArgs(ethers.ZeroAddress); + .to.be.revertedWithCustomError(this.ownable, 'OwnableInvalidOwner') + .withArgs(ethers.ZeroAddress); }); }); describe('renounce ownership', function () { it('loses ownership after renouncement', async function () { await expect(this.ownable.connect(this.owner).renounceOwnership()) - .to.emit(this.ownable, 'OwnershipTransferred') - .withArgs(this.owner.address, ethers.ZeroAddress); + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(this.owner.address, ethers.ZeroAddress); expect(await this.ownable.owner()).to.equal(ethers.ZeroAddress); }); it('prevents non-owners from renouncement', async function () { await expect(this.ownable.connect(this.other).renounceOwnership()) - .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') - .withArgs(this.other.address); + .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount') + .withArgs(this.other.address); }); it('allows to recover access using the internal _transferOwnership', async function () { await this.ownable.connect(this.owner).renounceOwnership(); await expect(this.ownable.$_transferOwnership(this.other.address)) - .to.emit(this.ownable, 'OwnershipTransferred') - .withArgs(ethers.ZeroAddress, this.other.address); + .to.emit(this.ownable, 'OwnershipTransferred') + .withArgs(ethers.ZeroAddress, this.other.address); expect(await this.ownable.owner()).to.equal(this.other.address); }); diff --git a/test/helpers/deploy.js b/test/helpers/deploy.js index 763708ad298..30817f609fd 100644 --- a/test/helpers/deploy.js +++ b/test/helpers/deploy.js @@ -1,20 +1,25 @@ const { ethers } = require('hardhat'); async function getFactory(name, opts = {}) { - return ethers.getContractFactory(name).then(contract => contract.connect(opts.signer || contract.runner)); + return ethers.getContractFactory(name).then(contract => contract.connect(opts.signer || contract.runner)); } function attach(name, address, opts = {}) { - return getFactory(name, opts).then(factory => factory.attach(address)); + return getFactory(name, opts).then(factory => factory.attach(address)); } function deploy(name, args = [], opts = {}) { - if (!Array.isArray(args)) { opts = args; args = []; } - return getFactory(name, opts).then(factory => factory.deploy(...args)).then(contract => contract.waitForDeployment()); + if (!Array.isArray(args)) { + opts = args; + args = []; + } + return getFactory(name, opts) + .then(factory => factory.deploy(...args)) + .then(contract => contract.waitForDeployment()); } module.exports = { - getFactory, - attach, - deploy, -}; \ No newline at end of file + getFactory, + attach, + deploy, +}; From c9b4e8dd45e64613941c6dad4161e2ec7ffebcee Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 13:43:31 +0200 Subject: [PATCH 03/17] Update hardhat.config.js --- hardhat.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.js b/hardhat.config.js index 9a7667a9f06..b15fb282edb 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -55,7 +55,7 @@ const argv = require('yargs/yargs')() }, }).argv; -// require('@nomiclabs/hardhat-truffle5'); +require('@nomiclabs/hardhat-truffle5'); // deprecated require('@nomicfoundation/hardhat-toolbox'); require('@nomicfoundation/hardhat-ethers'); require('hardhat-ignore-warnings'); From c46a45e3182ddca2bda0717f6001b8e7b8a0cdf6 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 15:47:21 +0200 Subject: [PATCH 04/17] add Ownable2Step --- test/access/Ownable2Step.test.js | 90 ++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/test/access/Ownable2Step.test.js b/test/access/Ownable2Step.test.js index bdbac48fa12..6e1a2fd9eb6 100644 --- a/test/access/Ownable2Step.test.js +++ b/test/access/Ownable2Step.test.js @@ -1,70 +1,84 @@ -const { constants, expectEvent } = require('@openzeppelin/test-helpers'); -const { ZERO_ADDRESS } = constants; +const { ethers } = require('hardhat'); const { expect } = require('chai'); -const { expectRevertCustomError } = require('../helpers/customError'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { deploy } = require('../helpers/deploy'); -const Ownable2Step = artifacts.require('$Ownable2Step'); - -contract('Ownable2Step', function (accounts) { - const [owner, accountA, accountB] = accounts; +async function fixture() { + const accounts = await ethers.getSigners(); + const owner = accounts.shift(); + const accountA = accounts.shift(); + const accountB = accounts.shift(); + const ownable2Step = await deploy('$Ownable2Step', [owner.address]); + return { accounts, owner, accountA, accountB, ownable2Step }; +} +describe('Ownable2Step', function () { beforeEach(async function () { - this.ownable2Step = await Ownable2Step.new(owner); + await loadFixture(fixture).then(results => Object.assign(this, results)); }); describe('transfer ownership', function () { it('starting a transfer does not change owner', async function () { - const receipt = await this.ownable2Step.transferOwnership(accountA, { from: owner }); - expectEvent(receipt, 'OwnershipTransferStarted', { previousOwner: owner, newOwner: accountA }); - expect(await this.ownable2Step.owner()).to.equal(owner); - expect(await this.ownable2Step.pendingOwner()).to.equal(accountA); + await expect(this.ownable2Step.connect(this.owner).transferOwnership(this.accountA.address)) + .to.emit(this.ownable2Step, 'OwnershipTransferStarted') + .withArgs(this.owner.address, this.accountA.address); + + expect(await this.ownable2Step.owner()).to.equal(this.owner.address); + expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA.address); }); it('changes owner after transfer', async function () { - await this.ownable2Step.transferOwnership(accountA, { from: owner }); - const receipt = await this.ownable2Step.acceptOwnership({ from: accountA }); - expectEvent(receipt, 'OwnershipTransferred', { previousOwner: owner, newOwner: accountA }); - expect(await this.ownable2Step.owner()).to.equal(accountA); - expect(await this.ownable2Step.pendingOwner()).to.not.equal(accountA); + await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA.address); + + await expect(this.ownable2Step.connect(this.accountA).acceptOwnership()) + .to.emit(this.ownable2Step, 'OwnershipTransferred') + .withArgs(this.owner.address, this.accountA.address); + + expect(await this.ownable2Step.owner()).to.equal(this.accountA.address); + expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress); }); it('guards transfer against invalid user', async function () { - await this.ownable2Step.transferOwnership(accountA, { from: owner }); - await expectRevertCustomError( - this.ownable2Step.acceptOwnership({ from: accountB }), - 'OwnableUnauthorizedAccount', - [accountB], - ); + await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA.address); + + await expect(this.ownable2Step.connect(this.accountB).acceptOwnership()) + .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount') + .withArgs(this.accountB.address); }); }); describe('renouncing ownership', async function () { it('changes owner after renouncing ownership', async function () { - await this.ownable2Step.renounceOwnership({ from: owner }); + await expect(this.ownable2Step.connect(this.owner).renounceOwnership()) + .to.emit(this.ownable2Step, 'OwnershipTransferred') + .withArgs(this.owner.address, ethers.ZeroAddress); + // If renounceOwnership is removed from parent an alternative is needed ... // without it is difficult to cleanly renounce with the two step process // see: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3620#discussion_r957930388 - expect(await this.ownable2Step.owner()).to.equal(ZERO_ADDRESS); + expect(await this.ownable2Step.owner()).to.equal(ethers.ZeroAddress); }); it('pending owner resets after renouncing ownership', async function () { - await this.ownable2Step.transferOwnership(accountA, { from: owner }); - expect(await this.ownable2Step.pendingOwner()).to.equal(accountA); - await this.ownable2Step.renounceOwnership({ from: owner }); - expect(await this.ownable2Step.pendingOwner()).to.equal(ZERO_ADDRESS); - await expectRevertCustomError( - this.ownable2Step.acceptOwnership({ from: accountA }), - 'OwnableUnauthorizedAccount', - [accountA], - ); + await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA.address); + expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA.address); + + await this.ownable2Step.connect(this.owner).renounceOwnership(); + expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress); + + await expect(this.ownable2Step.connect(this.accountA).acceptOwnership()) + .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount') + .withArgs(this.accountA.address); }); it('allows to recover access using the internal _transferOwnership', async function () { - await this.ownable2Step.renounceOwnership({ from: owner }); - const receipt = await this.ownable2Step.$_transferOwnership(accountA); - expectEvent(receipt, 'OwnershipTransferred'); + await this.ownable2Step.connect(this.owner).renounceOwnership(); + + await expect(this.ownable2Step.$_transferOwnership(this.accountA.address)) + .to.emit(this.ownable2Step, 'OwnershipTransferred') + .withArgs(ethers.ZeroAddress, this.accountA.address); - expect(await this.ownable2Step.owner()).to.equal(accountA); + expect(await this.ownable2Step.owner()).to.equal(this.accountA.address); }); }); }); From 328a34426d6f4fe8f8612d1e6e556da74c14f5d9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 18:57:03 +0200 Subject: [PATCH 05/17] remove deploy helper --- test/access/Ownable.test.js | 7 +++---- test/access/Ownable2Step.test.js | 3 +-- test/helpers/deploy.js | 25 ------------------------- 3 files changed, 4 insertions(+), 31 deletions(-) delete mode 100644 test/helpers/deploy.js diff --git a/test/access/Ownable.test.js b/test/access/Ownable.test.js index f9cfa0a9928..ec5fa8a4351 100644 --- a/test/access/Ownable.test.js +++ b/test/access/Ownable.test.js @@ -1,13 +1,12 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); -const { deploy, getFactory } = require('../helpers/deploy'); async function fixture() { const accounts = await ethers.getSigners(); // this is slow :/ const owner = accounts.shift(); const other = accounts.shift(); - const ownable = await deploy('$Ownable', [owner.address]); + const ownable = await ethers.deployContract('$Ownable', [owner.address]); return { accounts, owner, other, ownable }; } @@ -19,9 +18,9 @@ describe('Ownable', function () { it('rejects zero address for initialOwner', async function () { // checking a custom error requires a contract, or at least the interface // we can get it from the contract factory - const { interface } = await getFactory('$Ownable'); + const { interface } = await ethers.getContractFactory('$Ownable'); - await expect(deploy('$Ownable', [ethers.ZeroAddress])) + await expect(ethers.deployContract('$Ownable', [ethers.ZeroAddress])) .to.be.revertedWithCustomError({ interface }, 'OwnableInvalidOwner') .withArgs(ethers.ZeroAddress); }); diff --git a/test/access/Ownable2Step.test.js b/test/access/Ownable2Step.test.js index 6e1a2fd9eb6..307a8245f5d 100644 --- a/test/access/Ownable2Step.test.js +++ b/test/access/Ownable2Step.test.js @@ -1,14 +1,13 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); -const { deploy } = require('../helpers/deploy'); async function fixture() { const accounts = await ethers.getSigners(); const owner = accounts.shift(); const accountA = accounts.shift(); const accountB = accounts.shift(); - const ownable2Step = await deploy('$Ownable2Step', [owner.address]); + const ownable2Step = await ethers.deployContract('$Ownable2Step', [owner.address]); return { accounts, owner, accountA, accountB, ownable2Step }; } diff --git a/test/helpers/deploy.js b/test/helpers/deploy.js deleted file mode 100644 index 30817f609fd..00000000000 --- a/test/helpers/deploy.js +++ /dev/null @@ -1,25 +0,0 @@ -const { ethers } = require('hardhat'); - -async function getFactory(name, opts = {}) { - return ethers.getContractFactory(name).then(contract => contract.connect(opts.signer || contract.runner)); -} - -function attach(name, address, opts = {}) { - return getFactory(name, opts).then(factory => factory.attach(address)); -} - -function deploy(name, args = [], opts = {}) { - if (!Array.isArray(args)) { - opts = args; - args = []; - } - return getFactory(name, opts) - .then(factory => factory.deploy(...args)) - .then(contract => contract.waitForDeployment()); -} - -module.exports = { - getFactory, - attach, - deploy, -}; From 7c12232e29f0071b998ca93bd9b9545a734e6906 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 19:06:08 +0200 Subject: [PATCH 06/17] add deprecation notices --- test/helpers/chainid.js | 2 ++ test/helpers/create.js | 22 +++------------------- test/helpers/customError.js | 2 ++ 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/test/helpers/chainid.js b/test/helpers/chainid.js index 58757eb80f9..693a822e559 100644 --- a/test/helpers/chainid.js +++ b/test/helpers/chainid.js @@ -7,4 +7,6 @@ async function getChainId() { module.exports = { getChainId, + // TODO: when tests are ready to support bigint chainId + // getChainId: ethers.provider.getNetwork().then(network => network.chainId), }; diff --git a/test/helpers/create.js b/test/helpers/create.js index 98a0d4c4787..719937e74d0 100644 --- a/test/helpers/create.js +++ b/test/helpers/create.js @@ -1,22 +1,6 @@ -const RLP = require('rlp'); - -function computeCreateAddress(deployer, nonce) { - return web3.utils.toChecksumAddress(web3.utils.sha3(RLP.encode([deployer.address ?? deployer, nonce])).slice(-40)); -} - -function computeCreate2Address(saltHex, bytecode, deployer) { - return web3.utils.toChecksumAddress( - web3.utils - .sha3( - `0x${['ff', deployer.address ?? deployer, saltHex, web3.utils.soliditySha3(bytecode)] - .map(x => x.replace(/0x/, '')) - .join('')}`, - ) - .slice(-40), - ); -} +const { ethers } = require('hardhat'); module.exports = { - computeCreateAddress, - computeCreate2Address, + computeCreateAddress: (from, nonce) => ethers.getCreateAddress({ from, nonce }), + computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(ethers.toBeArray(bytecode))), }; diff --git a/test/helpers/customError.js b/test/helpers/customError.js index ea5c36820c5..acc3214eb80 100644 --- a/test/helpers/customError.js +++ b/test/helpers/customError.js @@ -1,3 +1,5 @@ +// DEPRECATED: replace with hardhat-toolbox chai matchers. + const { expect } = require('chai'); /** Revert handler that supports custom errors. */ From 517ad8785f06582c29e301b7041550790c560e4d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 19:15:03 +0200 Subject: [PATCH 07/17] up --- test/helpers/create.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/create.js b/test/helpers/create.js index 719937e74d0..797211ec4c9 100644 --- a/test/helpers/create.js +++ b/test/helpers/create.js @@ -2,5 +2,5 @@ const { ethers } = require('hardhat'); module.exports = { computeCreateAddress: (from, nonce) => ethers.getCreateAddress({ from, nonce }), - computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(ethers.toBeArray(bytecode))), + computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(ethers.getBytes(bytecode))), }; From 9002e5f7ef8137a8bce62d9eaae54cab0f8cfa5c Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 19:15:47 +0200 Subject: [PATCH 08/17] up --- test/helpers/create.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/create.js b/test/helpers/create.js index 797211ec4c9..fa837395ab1 100644 --- a/test/helpers/create.js +++ b/test/helpers/create.js @@ -2,5 +2,5 @@ const { ethers } = require('hardhat'); module.exports = { computeCreateAddress: (from, nonce) => ethers.getCreateAddress({ from, nonce }), - computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(ethers.getBytes(bytecode))), + computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(bytecode)), }; From 0c982dc89ab98b695f2d25ad071d48291b33ce05 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 20:41:27 +0200 Subject: [PATCH 09/17] remove create/create2 helper --- .../extensions/GovernorTimelockCompound.test.js | 4 ++-- test/helpers/create.js | 6 ------ test/proxy/Clones.test.js | 4 ++-- test/proxy/transparent/ProxyAdmin.test.js | 4 ++-- .../TransparentUpgradeableProxy.behaviour.js | 5 ++--- test/utils/Create2.test.js | 14 +++++++------- 6 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 test/helpers/create.js diff --git a/test/governance/extensions/GovernorTimelockCompound.test.js b/test/governance/extensions/GovernorTimelockCompound.test.js index e9d6f83736a..56191eb5056 100644 --- a/test/governance/extensions/GovernorTimelockCompound.test.js +++ b/test/governance/extensions/GovernorTimelockCompound.test.js @@ -1,10 +1,10 @@ +const { ethers } = require('ethers'); const { constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); const { expect } = require('chai'); const Enums = require('../../helpers/enums'); const { GovernorHelper, proposalStatesToBitMap } = require('../../helpers/governance'); const { expectRevertCustomError } = require('../../helpers/customError'); -const { computeCreateAddress } = require('../../helpers/create'); const { clockFromReceipt } = require('../../helpers/time'); const Timelock = artifacts.require('CompTimelock'); @@ -41,7 +41,7 @@ contract('GovernorTimelockCompound', function (accounts) { // Need to predict governance address to set it as timelock admin with a delayed transfer const nonce = await web3.eth.getTransactionCount(deployer); - const predictGovernor = computeCreateAddress(deployer, nonce + 1); + const predictGovernor = ethers.getCreateAddress({ from: deployer, nonce: nonce + 1 }); this.timelock = await Timelock.new(predictGovernor, defaultDelay); this.mock = await Governor.new( diff --git a/test/helpers/create.js b/test/helpers/create.js deleted file mode 100644 index fa837395ab1..00000000000 --- a/test/helpers/create.js +++ /dev/null @@ -1,6 +0,0 @@ -const { ethers } = require('hardhat'); - -module.exports = { - computeCreateAddress: (from, nonce) => ethers.getCreateAddress({ from, nonce }), - computeCreate2Address: (salt, bytecode, from) => ethers.getCreate2Address(from, salt, ethers.keccak256(bytecode)), -}; diff --git a/test/proxy/Clones.test.js b/test/proxy/Clones.test.js index 0862778f786..ad3dd537ccc 100644 --- a/test/proxy/Clones.test.js +++ b/test/proxy/Clones.test.js @@ -1,6 +1,6 @@ +const { ethers } = require('ethers'); const { expectEvent } = require('@openzeppelin/test-helpers'); const { expect } = require('chai'); -const { computeCreate2Address } = require('../helpers/create'); const { expectRevertCustomError } = require('../helpers/customError'); const shouldBehaveLikeClone = require('./Clones.behaviour'); @@ -52,7 +52,7 @@ contract('Clones', function (accounts) { '5af43d82803e903d91602b57fd5bf3', ].join(''); - expect(computeCreate2Address(salt, creationCode, factory.address)).to.be.equal(predicted); + expect(ethers.getCreate2Address(factory.address, salt, ethers.keccak256(creationCode))).to.be.equal(predicted); expectEvent(await factory.$cloneDeterministic(implementation, salt), 'return$cloneDeterministic', { instance: predicted, diff --git a/test/proxy/transparent/ProxyAdmin.test.js b/test/proxy/transparent/ProxyAdmin.test.js index 4d1a54f6ab5..a3122eae334 100644 --- a/test/proxy/transparent/ProxyAdmin.test.js +++ b/test/proxy/transparent/ProxyAdmin.test.js @@ -1,3 +1,4 @@ +const { ethers } = require('hardhat'); const { expectRevert } = require('@openzeppelin/test-helpers'); const { expect } = require('chai'); const ImplV1 = artifacts.require('DummyImplementation'); @@ -8,7 +9,6 @@ const ITransparentUpgradeableProxy = artifacts.require('ITransparentUpgradeableP const { getAddressInSlot, ImplementationSlot } = require('../../helpers/erc1967'); const { expectRevertCustomError } = require('../../helpers/customError'); -const { computeCreateAddress } = require('../../helpers/create'); contract('ProxyAdmin', function (accounts) { const [proxyAdminOwner, anotherAccount] = accounts; @@ -23,7 +23,7 @@ contract('ProxyAdmin', function (accounts) { const proxy = await TransparentUpgradeableProxy.new(this.implementationV1.address, proxyAdminOwner, initializeData); const proxyNonce = await web3.eth.getTransactionCount(proxy.address); - const proxyAdminAddress = computeCreateAddress(proxy.address, proxyNonce - 1); // Nonce already used + const proxyAdminAddress = ethers.getCreateAddress({ from: proxy.address, nonce: proxyNonce - 1 }); // Nonce already used this.proxyAdmin = await ProxyAdmin.at(proxyAdminAddress); this.proxy = await ITransparentUpgradeableProxy.at(proxy.address); diff --git a/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js b/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js index 103af7fc3a9..da4d992872b 100644 --- a/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js +++ b/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js @@ -4,8 +4,7 @@ const { getAddressInSlot, ImplementationSlot, AdminSlot } = require('../../helpe const { expectRevertCustomError } = require('../../helpers/customError'); const { expect } = require('chai'); -const { web3 } = require('hardhat'); -const { computeCreateAddress } = require('../../helpers/create'); +const { ethers, web3 } = require('hardhat'); const { impersonate } = require('../../helpers/account'); const Implementation1 = artifacts.require('Implementation1'); @@ -27,7 +26,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy(createProx const proxy = await createProxy(logic, initData, opts); // Expect proxy admin to be the first and only contract created by the proxy - const proxyAdminAddress = computeCreateAddress(proxy.address, 1); + const proxyAdminAddress = ethers.getCreateAddress({ from: proxy.address, nonce: 1 }); await impersonate(proxyAdminAddress); return { diff --git a/test/utils/Create2.test.js b/test/utils/Create2.test.js index 336ab1acc23..5327128a339 100644 --- a/test/utils/Create2.test.js +++ b/test/utils/Create2.test.js @@ -1,6 +1,6 @@ -const { balance, ether, expectEvent, expectRevert, send } = require('@openzeppelin/test-helpers'); +const { ethers } = require('hardhat'); const { expect } = require('chai'); -const { computeCreate2Address } = require('../helpers/create'); +const { balance, ether, expectEvent, expectRevert, send } = require('@openzeppelin/test-helpers'); const { expectRevertCustomError } = require('../helpers/customError'); const Create2 = artifacts.require('$Create2'); @@ -26,7 +26,7 @@ contract('Create2', function (accounts) { describe('computeAddress', function () { it('computes the correct contract address', async function () { const onChainComputed = await this.factory.$computeAddress(saltHex, web3.utils.keccak256(constructorByteCode)); - const offChainComputed = computeCreate2Address(saltHex, constructorByteCode, this.factory.address); + const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); expect(onChainComputed).to.equal(offChainComputed); }); @@ -36,14 +36,14 @@ contract('Create2', function (accounts) { web3.utils.keccak256(constructorByteCode), deployerAccount, ); - const offChainComputed = computeCreate2Address(saltHex, constructorByteCode, deployerAccount); + const offChainComputed = ethers.getCreate2Address(deployerAccount, saltHex, ethers.keccak256(constructorByteCode)); expect(onChainComputed).to.equal(offChainComputed); }); }); describe('deploy', function () { it('deploys a contract without constructor', async function () { - const offChainComputed = computeCreate2Address(saltHex, ConstructorLessContract.bytecode, this.factory.address); + const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(ConstructorLessContract.bytecode)); expectEvent(await this.factory.$deploy(0, saltHex, ConstructorLessContract.bytecode), 'return$deploy', { addr: offChainComputed, @@ -53,7 +53,7 @@ contract('Create2', function (accounts) { }); it('deploys a contract with constructor arguments', async function () { - const offChainComputed = computeCreate2Address(saltHex, constructorByteCode, this.factory.address); + const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); expectEvent(await this.factory.$deploy(0, saltHex, constructorByteCode), 'return$deploy', { addr: offChainComputed, @@ -69,7 +69,7 @@ contract('Create2', function (accounts) { await send.ether(deployerAccount, this.factory.address, deposit); expect(await balance.current(this.factory.address)).to.be.bignumber.equal(deposit); - const offChainComputed = computeCreate2Address(saltHex, constructorByteCode, this.factory.address); + const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); expectEvent(await this.factory.$deploy(deposit, saltHex, constructorByteCode), 'return$deploy', { addr: offChainComputed, From 4f935ffa63f5b3e45bd796d184498a3a4f8799a6 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 20:46:56 +0200 Subject: [PATCH 10/17] extract selector from FunctionFragment --- test/helpers/methods.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/helpers/methods.js b/test/helpers/methods.js index cb30d8727cb..94f01cff018 100644 --- a/test/helpers/methods.js +++ b/test/helpers/methods.js @@ -1,5 +1,5 @@ -const { soliditySha3 } = require('web3-utils'); +const { ethers } = require('hardhat'); module.exports = { - selector: signature => soliditySha3(signature).substring(0, 10), + selector: signature => ethers.FunctionFragment.from(signature).selector, }; From 9db3f301834670a9dc9d65f0e07edcdbdf2202a0 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 21:05:58 +0200 Subject: [PATCH 11/17] migrate some helpers --- test/helpers/erc1967.js | 17 ++++++++--------- test/helpers/time.js | 12 ++++++------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/test/helpers/erc1967.js b/test/helpers/erc1967.js index 4ad92c55c99..50542c89a9f 100644 --- a/test/helpers/erc1967.js +++ b/test/helpers/erc1967.js @@ -1,3 +1,4 @@ +const { ethers } = require('hardhat'); const { getStorageAt, setStorageAt } = require('@nomicfoundation/hardhat-network-helpers'); const ImplementationLabel = 'eip1967.proxy.implementation'; @@ -5,29 +6,27 @@ const AdminLabel = 'eip1967.proxy.admin'; const BeaconLabel = 'eip1967.proxy.beacon'; function labelToSlot(label) { - return '0x' + web3.utils.toBN(web3.utils.keccak256(label)).subn(1).toString(16); + return ethers.toBeHex(BigInt(ethers.keccak256(ethers.toUtf8Bytes(label))) - 1n); } function getSlot(address, slot) { return getStorageAt( - web3.utils.isAddress(address) ? address : address.address, - web3.utils.isHex(slot) ? slot : labelToSlot(slot), + ethers.isAddress(address) ? address : address.address, + ethers.isBytesLike(slot) ? slot : labelToSlot(slot), ); } function setSlot(address, slot, value) { - const hexValue = web3.utils.isHex(value) ? value : web3.utils.toHex(value); - return setStorageAt( - web3.utils.isAddress(address) ? address : address.address, - web3.utils.isHex(slot) ? slot : labelToSlot(slot), - web3.utils.padLeft(hexValue, 64), + ethers.isAddress(address) ? address : address.address, + ethers.isBytesLike(slot) ? slot : labelToSlot(slot), + value, ); } async function getAddressInSlot(address, slot) { const slotValue = await getSlot(address, slot); - return web3.utils.toChecksumAddress(slotValue.substring(slotValue.length - 40)); + return ethers.getAddress(slotValue.substring(slotValue.length - 40)); } module.exports = { diff --git a/test/helpers/time.js b/test/helpers/time.js index 30df8dc32ea..a1ddde515b1 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -1,17 +1,17 @@ -const ozHelpers = require('@openzeppelin/test-helpers'); -const helpers = require('@nomicfoundation/hardhat-network-helpers'); +const { time, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers'); module.exports = { clock: { - blocknumber: () => helpers.time.latestBlock(), - timestamp: () => helpers.time.latest(), + blocknumber: () => time.latestBlock(), + timestamp: () => time.latest(), }, clockFromReceipt: { blocknumber: receipt => Promise.resolve(receipt.blockNumber), timestamp: receipt => web3.eth.getBlock(receipt.blockNumber).then(block => block.timestamp), + // timestamp: receipt => receipt.getBlock().then(block => block.timestamp), }, forward: { - blocknumber: ozHelpers.time.advanceBlockTo, - timestamp: helpers.time.increaseTo, + blocknumber: mineUpTo, + timestamp: time.increaseTo, }, }; From d10e603d39127df0fb16b4bee64c908a47c95c28 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 5 Oct 2023 21:09:06 +0200 Subject: [PATCH 12/17] migrate chainId helpers --- test/helpers/chainid.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/test/helpers/chainid.js b/test/helpers/chainid.js index 693a822e559..e8181d55c26 100644 --- a/test/helpers/chainid.js +++ b/test/helpers/chainid.js @@ -1,12 +1,6 @@ -const hre = require('hardhat'); - -async function getChainId() { - const chainIdHex = await hre.network.provider.send('eth_chainId', []); - return new hre.web3.utils.BN(chainIdHex, 'hex'); -} +const { ethers } = require('hardhat'); module.exports = { - getChainId, - // TODO: when tests are ready to support bigint chainId - // getChainId: ethers.provider.getNetwork().then(network => network.chainId), + // TODO: remove conversion toNumber() when bigint are supported + getChainId: () => ethers.provider.getNetwork().then(network => ethers.toNumber(network.chainId)), }; From 3adcb85ad5d43fc49c2779902d841d6db2a1232b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 6 Oct 2023 13:52:06 +0200 Subject: [PATCH 13/17] wip --- test/helpers/account.js | 4 ++-- test/helpers/constants.js | 8 +++----- test/helpers/eip712.js | 27 ++++++++------------------ test/utils/cryptography/EIP712.test.js | 26 +++++++++---------------- 4 files changed, 22 insertions(+), 43 deletions(-) diff --git a/test/helpers/account.js b/test/helpers/account.js index 1b01a721455..8c0ea130b41 100644 --- a/test/helpers/account.js +++ b/test/helpers/account.js @@ -1,8 +1,8 @@ -const { web3 } = require('hardhat'); +const { ethers } = require('hardhat'); const { impersonateAccount, setBalance } = require('@nomicfoundation/hardhat-network-helpers'); // Hardhat default balance -const DEFAULT_BALANCE = web3.utils.toBN('10000000000000000000000'); +const DEFAULT_BALANCE = 10000n * ethers.WeiPerEther; async function impersonate(account, balance = DEFAULT_BALANCE) { await impersonateAccount(account); diff --git a/test/helpers/constants.js b/test/helpers/constants.js index 0f4d028cfce..6a3a82f4f16 100644 --- a/test/helpers/constants.js +++ b/test/helpers/constants.js @@ -1,7 +1,5 @@ -const MAX_UINT48 = web3.utils.toBN(1).shln(48).subn(1).toString(); -const MAX_UINT64 = web3.utils.toBN(1).shln(64).subn(1).toString(); - +// TODO: remove toString() when bigint are supported module.exports = { - MAX_UINT48, - MAX_UINT64, + MAX_UINT48: (2n ** 48n - 1n).toString(), + MAX_UINT64: (2n ** 64n - 1n).toString(), }; diff --git a/test/helpers/eip712.js b/test/helpers/eip712.js index b12a6233ec9..f6331f92fa7 100644 --- a/test/helpers/eip712.js +++ b/test/helpers/eip712.js @@ -1,5 +1,4 @@ -const ethSigUtil = require('eth-sig-util'); -const keccak256 = require('keccak256'); +const { ethers } = require('ethers'); const EIP712Domain = [ { name: 'name', type: 'string' }, @@ -17,14 +16,6 @@ const Permit = [ { name: 'deadline', type: 'uint256' }, ]; -function bufferToHexString(buffer) { - return '0x' + buffer.toString('hex'); -} - -function hexStringToBuffer(hexstr) { - return Buffer.from(hexstr.replace(/^0x/, ''), 'hex'); -} - async function getDomain(contract) { const { fields, name, version, chainId, verifyingContract, salt, extensions } = await contract.eip712Domain(); @@ -46,15 +37,13 @@ function domainType(domain) { return EIP712Domain.filter(({ name }) => domain[name] !== undefined); } -function domainSeparator(domain) { - return bufferToHexString( - ethSigUtil.TypedDataUtils.hashStruct('EIP712Domain', domain, { EIP712Domain: domainType(domain) }), - ); -} - function hashTypedData(domain, structHash) { - return bufferToHexString( - keccak256(Buffer.concat(['0x1901', domainSeparator(domain), structHash].map(str => hexStringToBuffer(str)))), + return ethers.keccak256( + Buffer.concat([ + '0x1901', + ethers.TypedDataEncoder.hashDomain(domain), + structHash, + ].map(ethers.toBeArray)) ); } @@ -62,6 +51,6 @@ module.exports = { Permit, getDomain, domainType, - domainSeparator, + domainSeparator: ethers.TypedDataEncoder.hashDomain, hashTypedData, }; diff --git a/test/utils/cryptography/EIP712.test.js b/test/utils/cryptography/EIP712.test.js index faf01f1a302..fc93b475dd4 100644 --- a/test/utils/cryptography/EIP712.test.js +++ b/test/utils/cryptography/EIP712.test.js @@ -1,6 +1,3 @@ -const ethSigUtil = require('eth-sig-util'); -const Wallet = require('ethereumjs-wallet').default; - const { getDomain, domainType, domainSeparator, hashTypedData } = require('../../helpers/eip712'); const { getChainId } = require('../../helpers/chainid'); const { mapValues } = require('../../helpers/iterate'); @@ -80,23 +77,18 @@ contract('EIP712', function (accounts) { contents: 'very interesting', }; - const data = { - types: { - EIP712Domain: this.domainType, - Mail: [ - { name: 'to', type: 'address' }, - { name: 'contents', type: 'string' }, - ], - }, - domain: this.domain, - primaryType: 'Mail', - message, + const types = { + Mail: [ + { name: 'to', type: 'address' }, + { name: 'contents', type: 'string' }, + ], }; - const wallet = Wallet.generate(); - const signature = ethSigUtil.signTypedMessage(wallet.getPrivateKey(), { data }); + const signer = ethers.Wallet.createRandom(); + const address = await signer.getAddress(); + const signature = await signer.signTypedData(this.domain, types, message); - await this.eip712.verify(signature, wallet.getAddressString(), message.to, message.contents); + await this.eip712.verify(signature, address, message.to, message.contents); }); it('name', async function () { From 7f18186a321f299628b6e90f415d1c9254999df3 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 17 Oct 2023 14:52:44 +0200 Subject: [PATCH 14/17] translate MerkleProof to ethers.js --- package-lock.json | 157 +++++------- package.json | 3 +- test/utils/cryptography/MerkleProof.test.js | 267 +++++++++----------- 3 files changed, 192 insertions(+), 235 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11586105968..ff5e16632fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/docs-utils": "^0.1.5", + "@openzeppelin/merkle-tree": "^1.0.5", "@openzeppelin/test-helpers": "^0.5.13", "@openzeppelin/upgrade-safe-transpiler": "^0.3.32", "@openzeppelin/upgrades-core": "^1.20.6", @@ -38,10 +39,8 @@ "hardhat-exposed": "^0.3.13", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.0", - "keccak256": "^1.0.2", "lodash.startcase": "^4.4.0", "lodash.zip": "^4.2.0", - "merkletreejs": "^0.2.13", "micromatch": "^4.0.2", "p-limit": "^3.1.0", "prettier": "^3.0.0", @@ -2595,6 +2594,73 @@ "node": ">=8" } }, + "node_modules/@openzeppelin/merkle-tree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz", + "integrity": "sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "ethereum-cryptography": "^1.1.2" + } + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@openzeppelin/merkle-tree/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, "node_modules/@openzeppelin/test-helpers": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/@openzeppelin/test-helpers/-/test-helpers-0.5.16.tgz", @@ -5209,12 +5275,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-reverse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-reverse/-/buffer-reverse-1.0.1.tgz", - "integrity": "sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==", - "dev": true - }, "node_modules/buffer-to-arraybuffer": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", @@ -6159,12 +6219,6 @@ "sha3": "^2.1.1" } }, - "node_modules/crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==", - "dev": true - }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -10212,47 +10266,6 @@ "node": ">=10.0.0" } }, - "node_modules/keccak256": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/keccak256/-/keccak256-1.0.6.tgz", - "integrity": "sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw==", - "dev": true, - "dependencies": { - "bn.js": "^5.2.0", - "buffer": "^6.0.3", - "keccak": "^3.0.2" - } - }, - "node_modules/keccak256/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/keccak256/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/keyv": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", @@ -10787,31 +10800,6 @@ "node": ">= 8" } }, - "node_modules/merkletreejs": { - "version": "0.2.32", - "resolved": "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.2.32.tgz", - "integrity": "sha512-TostQBiwYRIwSE5++jGmacu3ODcKAgqb0Y/pnIohXS7sWxh1gCkSptbmF1a43faehRDpcHf7J/kv0Ml2D/zblQ==", - "dev": true, - "dependencies": { - "bignumber.js": "^9.0.1", - "buffer-reverse": "^1.0.1", - "crypto-js": "^3.1.9-1", - "treeify": "^1.1.0", - "web3-utils": "^1.3.4" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/merkletreejs/node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -15271,15 +15259,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, - "node_modules/treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", diff --git a/package.json b/package.json index e6d28bce06c..ee36a8f8f57 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/docs-utils": "^0.1.5", + "@openzeppelin/merkle-tree": "^1.0.5", "@openzeppelin/test-helpers": "^0.5.13", "@openzeppelin/upgrade-safe-transpiler": "^0.3.32", "@openzeppelin/upgrades-core": "^1.20.6", @@ -78,10 +79,8 @@ "hardhat-exposed": "^0.3.13", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.0", - "keccak256": "^1.0.2", "lodash.startcase": "^4.4.0", "lodash.zip": "^4.2.0", - "merkletreejs": "^0.2.13", "micromatch": "^4.0.2", "p-limit": "^3.1.0", "prettier": "^3.0.0", diff --git a/test/utils/cryptography/MerkleProof.test.js b/test/utils/cryptography/MerkleProof.test.js index 5b87bc5252e..39d0dae9db4 100644 --- a/test/utils/cryptography/MerkleProof.test.js +++ b/test/utils/cryptography/MerkleProof.test.js @@ -1,207 +1,186 @@ -const { expectRevert } = require('@openzeppelin/test-helpers'); - -const { MerkleTree } = require('merkletreejs'); -const keccak256 = require('keccak256'); - +const { ethers } = require('hardhat'); const { expect } = require('chai'); -const { expectRevertCustomError } = require('../../helpers/customError'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { StandardMerkleTree } = require('@openzeppelin/merkle-tree'); + +const toElements = str => str.split('').map(e => [e]); +const hashPair = (a, b) => ethers.keccak256(Buffer.concat([a, b].sort(Buffer.compare))); -const MerkleProof = artifacts.require('$MerkleProof'); +async function fixture() { + const mock = await ethers.deployContract('$MerkleProof'); + return { mock }; +} -contract('MerkleProof', function () { +describe('MerkleProof', function () { beforeEach(async function () { - this.merkleProof = await MerkleProof.new(); + Object.assign(this, await loadFixture(fixture)); }); describe('verify', function () { it('returns true for a valid Merkle proof', async function () { - const elements = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''); - const merkleTree = new MerkleTree(elements, keccak256, { hashLeaves: true, sortPairs: true }); - - const root = merkleTree.getHexRoot(); - - const leaf = keccak256(elements[0]); + const merkleTree = StandardMerkleTree.of(toElements('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='), ['string']); - const proof = merkleTree.getHexProof(leaf); + const root = merkleTree.root; + const hash = merkleTree.leafHash(['A']); + const proof = merkleTree.getProof(['A']); - expect(await this.merkleProof.$verify(proof, root, leaf)).to.equal(true); - expect(await this.merkleProof.$verifyCalldata(proof, root, leaf)).to.equal(true); + expect(await this.mock.$verify(proof, root, hash)).to.equal(true); + expect(await this.mock.$verifyCalldata(proof, root, hash)).to.equal(true); // For demonstration, it is also possible to create valid proofs for certain 64-byte values *not* in elements: - const noSuchLeaf = keccak256( - Buffer.concat([keccak256(elements[0]), keccak256(elements[1])].sort(Buffer.compare)), + const noSuchLeaf = hashPair( + ethers.toBeArray(merkleTree.leafHash(['A'])), + ethers.toBeArray(merkleTree.leafHash(['B'])), ); - expect(await this.merkleProof.$verify(proof.slice(1), root, noSuchLeaf)).to.equal(true); - expect(await this.merkleProof.$verifyCalldata(proof.slice(1), root, noSuchLeaf)).to.equal(true); + expect(await this.mock.$verify(proof.slice(1), root, noSuchLeaf)).to.equal(true); + expect(await this.mock.$verifyCalldata(proof.slice(1), root, noSuchLeaf)).to.equal(true); }); it('returns false for an invalid Merkle proof', async function () { - const correctElements = ['a', 'b', 'c']; - const correctMerkleTree = new MerkleTree(correctElements, keccak256, { hashLeaves: true, sortPairs: true }); + const correctMerkleTree = StandardMerkleTree.of(toElements('abc'), ['string']); + const otherMerkleTree = StandardMerkleTree.of(toElements('def'), ['string']); - const correctRoot = correctMerkleTree.getHexRoot(); + const root = correctMerkleTree.root; + const hash = correctMerkleTree.leafHash(['a']); + const proof = otherMerkleTree.getProof(['d']); - const correctLeaf = keccak256(correctElements[0]); - - const badElements = ['d', 'e', 'f']; - const badMerkleTree = new MerkleTree(badElements); - - const badProof = badMerkleTree.getHexProof(badElements[0]); - - expect(await this.merkleProof.$verify(badProof, correctRoot, correctLeaf)).to.equal(false); - expect(await this.merkleProof.$verifyCalldata(badProof, correctRoot, correctLeaf)).to.equal(false); + expect(await this.mock.$verify(proof, root, hash)).to.equal(false); + expect(await this.mock.$verifyCalldata(proof, root, hash)).to.equal(false); }); it('returns false for a Merkle proof of invalid length', async function () { - const elements = ['a', 'b', 'c']; - const merkleTree = new MerkleTree(elements, keccak256, { hashLeaves: true, sortPairs: true }); - - const root = merkleTree.getHexRoot(); - - const leaf = keccak256(elements[0]); + const merkleTree = StandardMerkleTree.of(toElements('abc'), ['string']); - const proof = merkleTree.getHexProof(leaf); + const root = merkleTree.root; + const leaf = merkleTree.leafHash(['a']); + const proof = merkleTree.getProof(['a']); const badProof = proof.slice(0, proof.length - 5); - expect(await this.merkleProof.$verify(badProof, root, leaf)).to.equal(false); - expect(await this.merkleProof.$verifyCalldata(badProof, root, leaf)).to.equal(false); + expect(await this.mock.$verify(badProof, root, leaf)).to.equal(false); + expect(await this.mock.$verifyCalldata(badProof, root, leaf)).to.equal(false); }); }); describe('multiProofVerify', function () { it('returns true for a valid Merkle multi proof', async function () { - const leaves = ['a', 'b', 'c', 'd', 'e', 'f'].map(keccak256).sort(Buffer.compare); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); + const merkleTree = StandardMerkleTree.of(toElements('abcdef'), ['string']); - const root = merkleTree.getRoot(); - const proofLeaves = ['b', 'f', 'd'].map(keccak256).sort(Buffer.compare); - const proof = merkleTree.getMultiProof(proofLeaves); - const proofFlags = merkleTree.getProofFlags(proofLeaves, proof); + const root = merkleTree.root; + const { proof, proofFlags, leaves } = merkleTree.getMultiProof(toElements('bdf')); + const hashes = leaves.map(e => merkleTree.leafHash(e)); - expect(await this.merkleProof.$multiProofVerify(proof, proofFlags, root, proofLeaves)).to.equal(true); - expect(await this.merkleProof.$multiProofVerifyCalldata(proof, proofFlags, root, proofLeaves)).to.equal(true); + expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.equal(true); + expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.equal(true); }); it('returns false for an invalid Merkle multi proof', async function () { - const leaves = ['a', 'b', 'c', 'd', 'e', 'f'].map(keccak256).sort(Buffer.compare); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); - - const root = merkleTree.getRoot(); - const badProofLeaves = ['g', 'h', 'i'].map(keccak256).sort(Buffer.compare); - const badMerkleTree = new MerkleTree(badProofLeaves); - const badProof = badMerkleTree.getMultiProof(badProofLeaves); - const badProofFlags = badMerkleTree.getProofFlags(badProofLeaves, badProof); - - expect(await this.merkleProof.$multiProofVerify(badProof, badProofFlags, root, badProofLeaves)).to.equal(false); - expect(await this.merkleProof.$multiProofVerifyCalldata(badProof, badProofFlags, root, badProofLeaves)).to.equal( - false, - ); + const merkleTree = StandardMerkleTree.of(toElements('abcdef'), ['string']); + const otherMerkleTree = StandardMerkleTree.of(toElements('ghi'), ['string']); + + const root = merkleTree.root; + const { proof, proofFlags, leaves } = otherMerkleTree.getMultiProof(toElements('ghi')); + const hashes = leaves.map(e => merkleTree.leafHash(e)); + + expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.equal(false); + expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.equal(false); }); it('revert with invalid multi proof #1', async function () { - const fill = Buffer.alloc(32); // This could be anything, we are reconstructing a fake branch - const leaves = ['a', 'b', 'c', 'd'].map(keccak256).sort(Buffer.compare); - const badLeaf = keccak256('e'); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); - - const root = merkleTree.getRoot(); - - await expectRevertCustomError( - this.merkleProof.$multiProofVerify( - [leaves[1], fill, merkleTree.layers[1][1]], - [false, false, false], - root, - [leaves[0], badLeaf], // A, E - ), - 'MerkleProofInvalidMultiproof', - [], - ); - await expectRevertCustomError( - this.merkleProof.$multiProofVerifyCalldata( - [leaves[1], fill, merkleTree.layers[1][1]], - [false, false, false], - root, - [leaves[0], badLeaf], // A, E - ), - 'MerkleProofInvalidMultiproof', - [], + const merkleTree = StandardMerkleTree.of(toElements('abcd'), ['string']); + + const root = merkleTree.root; + const hashA = merkleTree.leafHash(['a']); + const hashB = merkleTree.leafHash(['b']); + const hashCD = hashPair( + ethers.toBeArray(merkleTree.leafHash(['c'])), + ethers.toBeArray(merkleTree.leafHash(['d'])), ); + const hashE = merkleTree.leafHash(['e']); // incorrect (not part of the tree) + const fill = ethers.randomBytes(32); + + await expect(this.mock.$multiProofVerify( + [hashB, fill, hashCD], + [false, false, false], + root, + [hashA, hashE], + )) + .to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); + + await expect(this.mock.$multiProofVerifyCalldata( + [hashB, fill, hashCD], + [false, false, false], + root, + [hashA, hashE], + )) + .to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); }); it('revert with invalid multi proof #2', async function () { - const fill = Buffer.alloc(32); // This could be anything, we are reconstructing a fake branch - const leaves = ['a', 'b', 'c', 'd'].map(keccak256).sort(Buffer.compare); - const badLeaf = keccak256('e'); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); - - const root = merkleTree.getRoot(); - - await expectRevert( - this.merkleProof.$multiProofVerify( - [leaves[1], fill, merkleTree.layers[1][1]], - [false, false, false, false], - root, - [badLeaf, leaves[0]], // A, E - ), - 'reverted with panic code 0x32', - ); - - await expectRevert( - this.merkleProof.$multiProofVerifyCalldata( - [leaves[1], fill, merkleTree.layers[1][1]], - [false, false, false, false], - root, - [badLeaf, leaves[0]], // A, E - ), - 'reverted with panic code 0x32', + const merkleTree = StandardMerkleTree.of(toElements('abcd'), ['string']); + + const root = merkleTree.root; + const hashA = merkleTree.leafHash(['a']); + const hashB = merkleTree.leafHash(['b']); + const hashCD = hashPair( + ethers.toBeArray(merkleTree.leafHash(['c'])), + ethers.toBeArray(merkleTree.leafHash(['d'])), ); + const hashE = merkleTree.leafHash(['e']); // incorrect (not part of the tree) + const fill = ethers.randomBytes(32); + + await expect(this.mock.$multiProofVerify( + [hashB, fill, hashCD], + [false, false, false, false], + root, + [hashE, hashA], + )) + .to.be.revertedWithPanic(0x32); + + await expect(this.mock.$multiProofVerifyCalldata( + [hashB, fill, hashCD], + [false, false, false, false], + root, + [hashE, hashA], + )) + .to.be.revertedWithPanic(0x32); }); it('limit case: works for tree containing a single leaf', async function () { - const leaves = ['a'].map(keccak256).sort(Buffer.compare); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); + const merkleTree = StandardMerkleTree.of(toElements('a'), ['string']); - const root = merkleTree.getRoot(); - const proofLeaves = ['a'].map(keccak256).sort(Buffer.compare); - const proof = merkleTree.getMultiProof(proofLeaves); - const proofFlags = merkleTree.getProofFlags(proofLeaves, proof); + const root = merkleTree.root; + const { proof, proofFlags, leaves } = merkleTree.getMultiProof(toElements('a')); + const hashes = leaves.map(e => merkleTree.leafHash(e)); - expect(await this.merkleProof.$multiProofVerify(proof, proofFlags, root, proofLeaves)).to.equal(true); - expect(await this.merkleProof.$multiProofVerifyCalldata(proof, proofFlags, root, proofLeaves)).to.equal(true); + expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.equal(true); + expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.equal(true); }); it('limit case: can prove empty leaves', async function () { - const leaves = ['a', 'b', 'c', 'd'].map(keccak256).sort(Buffer.compare); - const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); + const merkleTree = StandardMerkleTree.of(toElements('abcd'), ['string']); - const root = merkleTree.getRoot(); - expect(await this.merkleProof.$multiProofVerify([root], [], root, [])).to.equal(true); - expect(await this.merkleProof.$multiProofVerifyCalldata([root], [], root, [])).to.equal(true); + const root = merkleTree.root; + expect(await this.mock.$multiProofVerify([root], [], root, [])).to.equal(true); + expect(await this.mock.$multiProofVerifyCalldata([root], [], root, [])).to.equal(true); }); it('reverts processing manipulated proofs with a zero-value node at depth 1', async function () { // Create a merkle tree that contains a zero leaf at depth 1 - const leaves = [keccak256('real leaf'), Buffer.alloc(32, 0)]; - const merkleTree = new MerkleTree(leaves, keccak256, { sortPairs: true }); - - const root = merkleTree.getRoot(); + const leave = ethers.id('real leaf') + const root = hashPair(ethers.toBeArray(leave), Buffer.alloc(32, 0)); // Now we can pass any **malicious** fake leaves as valid! - const maliciousLeaves = ['malicious', 'leaves'].map(keccak256).sort(Buffer.compare); - const maliciousProof = [leaves[0], leaves[0]]; + const maliciousLeaves = ['malicious', 'leaves'].map(ethers.id).map(ethers.toBeArray).sort(Buffer.compare); + const maliciousProof = [leave, leave]; const maliciousProofFlags = [true, true, false]; - await expectRevertCustomError( - this.merkleProof.$multiProofVerify(maliciousProof, maliciousProofFlags, root, maliciousLeaves), - 'MerkleProofInvalidMultiproof', - [], - ); + await expect( + this.mock.$multiProofVerify(maliciousProof, maliciousProofFlags, root, maliciousLeaves), + ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); - await expectRevertCustomError( - this.merkleProof.$multiProofVerifyCalldata(maliciousProof, maliciousProofFlags, root, maliciousLeaves), - 'MerkleProofInvalidMultiproof', - [], - ); + await expect( + this.mock.$multiProofVerifyCalldata(maliciousProof, maliciousProofFlags, root, maliciousLeaves), + ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); }); }); }); From 5a2dec19527573fd6ad75404bcdf92142aee59ae Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 17 Oct 2023 15:04:17 +0200 Subject: [PATCH 15/17] fix lint --- test/helpers/eip712.js | 6 +-- test/utils/Create2.test.js | 30 ++++++++++-- test/utils/cryptography/EIP712.test.js | 1 + test/utils/cryptography/MerkleProof.test.js | 51 ++++++++------------- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/test/helpers/eip712.js b/test/helpers/eip712.js index f6331f92fa7..0dcda9ae432 100644 --- a/test/helpers/eip712.js +++ b/test/helpers/eip712.js @@ -39,11 +39,7 @@ function domainType(domain) { function hashTypedData(domain, structHash) { return ethers.keccak256( - Buffer.concat([ - '0x1901', - ethers.TypedDataEncoder.hashDomain(domain), - structHash, - ].map(ethers.toBeArray)) + Buffer.concat(['0x1901', ethers.TypedDataEncoder.hashDomain(domain), structHash].map(ethers.toBeArray)), ); } diff --git a/test/utils/Create2.test.js b/test/utils/Create2.test.js index 5327128a339..a4ad992370d 100644 --- a/test/utils/Create2.test.js +++ b/test/utils/Create2.test.js @@ -26,7 +26,11 @@ contract('Create2', function (accounts) { describe('computeAddress', function () { it('computes the correct contract address', async function () { const onChainComputed = await this.factory.$computeAddress(saltHex, web3.utils.keccak256(constructorByteCode)); - const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); + const offChainComputed = ethers.getCreate2Address( + this.factory.address, + saltHex, + ethers.keccak256(constructorByteCode), + ); expect(onChainComputed).to.equal(offChainComputed); }); @@ -36,14 +40,22 @@ contract('Create2', function (accounts) { web3.utils.keccak256(constructorByteCode), deployerAccount, ); - const offChainComputed = ethers.getCreate2Address(deployerAccount, saltHex, ethers.keccak256(constructorByteCode)); + const offChainComputed = ethers.getCreate2Address( + deployerAccount, + saltHex, + ethers.keccak256(constructorByteCode), + ); expect(onChainComputed).to.equal(offChainComputed); }); }); describe('deploy', function () { it('deploys a contract without constructor', async function () { - const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(ConstructorLessContract.bytecode)); + const offChainComputed = ethers.getCreate2Address( + this.factory.address, + saltHex, + ethers.keccak256(ConstructorLessContract.bytecode), + ); expectEvent(await this.factory.$deploy(0, saltHex, ConstructorLessContract.bytecode), 'return$deploy', { addr: offChainComputed, @@ -53,7 +65,11 @@ contract('Create2', function (accounts) { }); it('deploys a contract with constructor arguments', async function () { - const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); + const offChainComputed = ethers.getCreate2Address( + this.factory.address, + saltHex, + ethers.keccak256(constructorByteCode), + ); expectEvent(await this.factory.$deploy(0, saltHex, constructorByteCode), 'return$deploy', { addr: offChainComputed, @@ -69,7 +85,11 @@ contract('Create2', function (accounts) { await send.ether(deployerAccount, this.factory.address, deposit); expect(await balance.current(this.factory.address)).to.be.bignumber.equal(deposit); - const offChainComputed = ethers.getCreate2Address(this.factory.address, saltHex, ethers.keccak256(constructorByteCode)); + const offChainComputed = ethers.getCreate2Address( + this.factory.address, + saltHex, + ethers.keccak256(constructorByteCode), + ); expectEvent(await this.factory.$deploy(deposit, saltHex, constructorByteCode), 'return$deploy', { addr: offChainComputed, diff --git a/test/utils/cryptography/EIP712.test.js b/test/utils/cryptography/EIP712.test.js index fc93b475dd4..dfad67906b3 100644 --- a/test/utils/cryptography/EIP712.test.js +++ b/test/utils/cryptography/EIP712.test.js @@ -1,3 +1,4 @@ +const { ethers } = require('hardhat'); const { getDomain, domainType, domainSeparator, hashTypedData } = require('../../helpers/eip712'); const { getChainId } = require('../../helpers/chainid'); const { mapValues } = require('../../helpers/iterate'); diff --git a/test/utils/cryptography/MerkleProof.test.js b/test/utils/cryptography/MerkleProof.test.js index 39d0dae9db4..73e1ada950f 100644 --- a/test/utils/cryptography/MerkleProof.test.js +++ b/test/utils/cryptography/MerkleProof.test.js @@ -18,7 +18,10 @@ describe('MerkleProof', function () { describe('verify', function () { it('returns true for a valid Merkle proof', async function () { - const merkleTree = StandardMerkleTree.of(toElements('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='), ['string']); + const merkleTree = StandardMerkleTree.of( + toElements('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='), + ['string'], + ); const root = merkleTree.root; const hash = merkleTree.leafHash(['A']); @@ -98,21 +101,13 @@ describe('MerkleProof', function () { const hashE = merkleTree.leafHash(['e']); // incorrect (not part of the tree) const fill = ethers.randomBytes(32); - await expect(this.mock.$multiProofVerify( - [hashB, fill, hashCD], - [false, false, false], - root, - [hashA, hashE], - )) - .to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); - - await expect(this.mock.$multiProofVerifyCalldata( - [hashB, fill, hashCD], - [false, false, false], - root, - [hashA, hashE], - )) - .to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); + await expect( + this.mock.$multiProofVerify([hashB, fill, hashCD], [false, false, false], root, [hashA, hashE]), + ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); + + await expect( + this.mock.$multiProofVerifyCalldata([hashB, fill, hashCD], [false, false, false], root, [hashA, hashE]), + ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof'); }); it('revert with invalid multi proof #2', async function () { @@ -128,21 +123,13 @@ describe('MerkleProof', function () { const hashE = merkleTree.leafHash(['e']); // incorrect (not part of the tree) const fill = ethers.randomBytes(32); - await expect(this.mock.$multiProofVerify( - [hashB, fill, hashCD], - [false, false, false, false], - root, - [hashE, hashA], - )) - .to.be.revertedWithPanic(0x32); - - await expect(this.mock.$multiProofVerifyCalldata( - [hashB, fill, hashCD], - [false, false, false, false], - root, - [hashE, hashA], - )) - .to.be.revertedWithPanic(0x32); + await expect( + this.mock.$multiProofVerify([hashB, fill, hashCD], [false, false, false, false], root, [hashE, hashA]), + ).to.be.revertedWithPanic(0x32); + + await expect( + this.mock.$multiProofVerifyCalldata([hashB, fill, hashCD], [false, false, false, false], root, [hashE, hashA]), + ).to.be.revertedWithPanic(0x32); }); it('limit case: works for tree containing a single leaf', async function () { @@ -166,7 +153,7 @@ describe('MerkleProof', function () { it('reverts processing manipulated proofs with a zero-value node at depth 1', async function () { // Create a merkle tree that contains a zero leaf at depth 1 - const leave = ethers.id('real leaf') + const leave = ethers.id('real leaf'); const root = hashPair(ethers.toBeArray(leave), Buffer.alloc(32, 0)); // Now we can pass any **malicious** fake leaves as valid! From ab35ed451ebd1facdf3d8dd72ffb9e586322ca30 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 17 Oct 2023 15:07:03 +0200 Subject: [PATCH 16/17] Update test/helpers/time.js --- test/helpers/time.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/helpers/time.js b/test/helpers/time.js index a1ddde515b1..7a2a13d23e4 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -8,6 +8,7 @@ module.exports = { clockFromReceipt: { blocknumber: receipt => Promise.resolve(receipt.blockNumber), timestamp: receipt => web3.eth.getBlock(receipt.blockNumber).then(block => block.timestamp), + // TODO: update for ethers receipt // timestamp: receipt => receipt.getBlock().then(block => block.timestamp), }, forward: { From c823e22754fb637394e4f91425cda55bf4c62708 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 17 Oct 2023 22:05:36 +0200 Subject: [PATCH 17/17] fix tests --- test/helpers/eip712.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/helpers/eip712.js b/test/helpers/eip712.js index 0dcda9ae432..0dd78b7e05e 100644 --- a/test/helpers/eip712.js +++ b/test/helpers/eip712.js @@ -23,7 +23,15 @@ async function getDomain(contract) { throw Error('Extensions not implemented'); } - const domain = { name, version, chainId, verifyingContract, salt }; + const domain = { + name, + version, + // TODO: remove check when contracts are all migrated to ethers + chainId: web3.utils.isBN(chainId) ? chainId.toNumber() : chainId, + verifyingContract, + salt, + }; + for (const [i, { name }] of EIP712Domain.entries()) { if (!(fields & (1 << i))) { delete domain[name];