diff --git a/.circleci/config.yml b/.circleci/config.yml index 516ed3156..c218d088a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,75 +1,81 @@ version: 2.1 -orbs: - discord: antonioned/discord@0.1.0 -jobs: - build: - working_directory: ~/repo +executors: + nodeimage: docker: - image: cimg/node:16.14 + working_directory: ~/repo resource_class: xlarge + +jobs: + build: + executor: nodeimage steps: - - checkout - - run: - name: 'Update NPM' - command: sudo npm install -g npm@8.5.3 - - run: - name: 'Set caching variables' - command: | - LAST_SUCCESSFUL_BUILD_URL="https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/master?filter=successful&limit=1" - LAST_SUCCESSFUL_COMMIT=`curl -Ss -u "$CIRCLE_TOKEN:" $LAST_SUCCESSFUL_BUILD_URL | jq -r '.[0]["vcs_revision"]'` - echo $LAST_SUCCESSFUL_COMMIT > /tmp/last-successful-commit - echo $CIRCLE_SHA1 > /tmp/current-commit - - restore_cache: - keys: - - build-cache-{{ .Branch }}-{{ checksum "/tmp/last-successful-commit" }} - - run: + - checkout + - restore_cache: # This one restores node_modules, and .npm if the package-lock.json checksum is the same + key: package-cache-{{ checksum "package-lock.json" }} + - run: # we use npm install and not npm ci because npm ci removes node-modules entirely name: Install dependencies command: npm install + - save_cache: # Save the node_modules and .npm directories into the cache by the checksum of package-lock.json + key: package-cache-{{ checksum "package-lock.json" }} + paths: + - node_modules + - run: # generate a checksum of all of the source solidity files to see if they have changed, which we use as the key for caching + name: Generate solidity source checksum + command: ./sol-checksum.sh /tmp/sol-checksum.txt + - restore_cache: # Restore the solidity files cache the same way we do node_modules (by the checksum of the .json file) + key: solcache-{{ checksum "/tmp/sol-checksum.txt" }} - run: name: Compile contracts command: npm run compile:hardhat - - save_cache: - key: repo-{{ .Environment.CIRCLE_SHA1 }} + - run: # generate a checksum of all of the source solidity files to see if they have changed, which we use as the key for caching + name: Generate solidity source checksum (again) + command: ./sol-checksum.sh /tmp/sol-checksum.txt + - save_cache: # Save the solidity files cache, the compiled artifacts, and the generated types + key: solcache-{{ checksum "/tmp/sol-checksum.txt" }} + paths: + - artifacts + - types/contracts + - cache/solidity-files-cache.json + - restore_cache: # Restore the hardhat network fork cache if the hardhat-config hasn't changed + key: hardhat-config-{{ checksum "hardhat.config.ts" }} + - persist_to_workspace: + root: ~/repo paths: - - ~/repo + - ./ lint: working_directory: ~/repo - docker: - - image: cimg/node:16.14 + executor: nodeimage steps: - - restore_cache: - keys: - - repo-{{ .Environment.CIRCLE_SHA1 }} + - attach_workspace: + at: ./ - run: name: Run linter command: npm run lint test: working_directory: ~/repo - docker: - - image: cimg/node:16.14 + executor: nodeimage parallelism: 16 - resource_class: large steps: - - restore_cache: - keys: - - repo-{{ .Environment.CIRCLE_SHA1 }} + - attach_workspace: + at: ./ - run: name: Run tests command: | circleci tests glob "test/unit/**/*.ts" | circleci tests split --split-by=filesize > /tmp/tests-to-run npm run test:hardhat $(cat /tmp/tests-to-run) - store_test_results: - path: test-results + path: test-results - store_artifacts: - path: test-results + path: test-results test-forge: working_directory: ~/repo - docker: - - image: cimg/node:16.14 - resource_class: xlarge + executor: nodeimage steps: + - attach_workspace: + at: ./ - checkout - restore_cache: keys: @@ -80,7 +86,7 @@ jobs: - run: name: Finish setting up env command: echo "export PATH=$PATH:$(pwd)/.foundry/bin" >> /home/circleci/.bashrc - - run: + - run: name: Install Foundry command: curl -L https://foundry.paradigm.xyz | bash; source /home/circleci/.bashrc; $HOME/.foundry/bin/foundryup - run: @@ -91,37 +97,54 @@ jobs: e2e-test: working_directory: ~/repo - docker: - - image: cimg/node:16.14 - parallelism: 5 - resource_class: xlarge + executor: nodeimage + parallelism: 20 steps: + - attach_workspace: + at: ./ - restore_cache: - keys: - - repo-{{ .Environment.CIRCLE_SHA1 }} + key: fork-cache-{{ checksum "hardhat.config.ts" }} - run: name: Run end-to-end tests command: | - circleci tests glob "test/integration/**/*.ts" | circleci tests split --split-by=filesize > /tmp/tests-to-run + circleci tests glob "test/integration/tests/*.ts" | circleci tests split --split-by=filesize > /tmp/tests-to-run npm run test:e2e $(cat /tmp/tests-to-run) - store_test_results: - path: test-results + path: test-results - store_artifacts: - path: test-results + path: test-results + - persist_to_workspace: + root: ~/repo + paths: + - ./cache/hardhat-network-fork + + save-network-fork-cache: + working_directory: ~/repo + executor: nodeimage + steps: + - attach_workspace: + at: ./ + - save_cache: # Save the solidity files cache, the compiled artifacts, and the generated types + key: fork-cache-{{ checksum "hardhat.config.ts" }} + paths: + - cache/hardhat-network-fork workflows: main: jobs: - build - - lint: + - lint: requires: - build - test-forge: requires: - - build + - build - test: requires: - build - e2e-test: requires: - build + - save-network-fork-cache: + requires: + - e2e-test diff --git a/.gitignore b/.gitignore index 191a5e729..49fe27e92 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,4 @@ cache types/contracts .eslintcache .xml -out \ No newline at end of file +out diff --git a/contracts/core/TribeRoles.sol b/contracts/core/TribeRoles.sol index 84ffd2459..7992ef0a3 100644 --- a/contracts/core/TribeRoles.sol +++ b/contracts/core/TribeRoles.sol @@ -39,7 +39,7 @@ library TribeRoles { /// @notice capable of granting and revoking other TribeRoles from having veto power over a pod bytes32 internal constant POD_VETO_ADMIN = keccak256("POD_VETO_ADMIN"); - /// @notice can manage the majority of Tribe protocol parameters. Sets boundaries for MINOR_PARAM_ROLE. + /// @notice can manage the majority of Tribe protocol parameters bytes32 internal constant PARAMETER_ADMIN = keccak256("PARAMETER_ADMIN"); /// @notice manages the Collateralization Oracle as well as other protocol oracles. @@ -48,23 +48,23 @@ library TribeRoles { /// @notice manages TribalChief incentives and related functionality. bytes32 internal constant TRIBAL_CHIEF_ADMIN = keccak256("TRIBAL_CHIEF_ADMIN_ROLE"); + /// @notice admin of the Tokemak PCV deposits + bytes32 internal constant TOKEMAK_DEPOSIT_ADMIN_ROLE = keccak256("TOKEMAK_DEPOSIT_ADMIN_ROLE"); + /// @notice admin of PCVGuardian bytes32 internal constant PCV_GUARDIAN_ADMIN = keccak256("PCV_GUARDIAN_ADMIN_ROLE"); - /// @notice admin of all Minor Roles - bytes32 internal constant MINOR_ROLE_ADMIN = keccak256("MINOR_ROLE_ADMIN"); - /// @notice admin of the Fuse protocol bytes32 internal constant FUSE_ADMIN = keccak256("FUSE_ADMIN"); - /// @notice capable of vetoing DAO votes or optimistic timelocks - bytes32 internal constant VETO_ADMIN = keccak256("VETO_ADMIN"); + /// @notice admin of minting Fei for specific scoped contracts + bytes32 internal constant FEI_MINT_ADMIN = keccak256("FEI_MINT_ADMIN"); - /// @notice capable of setting FEI Minters within global rate limits and caps - bytes32 internal constant MINTER_ADMIN = keccak256("MINTER_ADMIN"); + /// @notice capable of admin functionality on PCVDeposits + bytes32 internal constant PCV_MINOR_PARAM_ROLE = keccak256("PCV_MINOR_PARAM_ROLE"); - /// @notice manages the constituents of Optimistic Timelocks, including Proposers and Executors - bytes32 internal constant OPTIMISTIC_ADMIN = keccak256("OPTIMISTIC_ADMIN"); + /// @notice capable of setting FEI Minters within global rate limits and caps + bytes32 internal constant RATE_LIMITED_MINTER_ADMIN = keccak256("RATE_LIMITED_MINTER_ADMIN"); /// @notice manages meta-governance actions, like voting & delegating. /// Also used to vote for gauge weights & similar liquid governance things. @@ -78,23 +78,26 @@ library TribeRoles { /// @notice manages whitelisting of gauges where the protocol's tokens can be staked bytes32 internal constant METAGOVERNANCE_GAUGE_ADMIN = keccak256("METAGOVERNANCE_GAUGE_ADMIN"); + /// @notice capable of performing swaps on Balancer LBP Swapper + bytes32 internal constant SWAP_ADMIN_ROLE = keccak256("SWAP_ADMIN_ROLE"); + + /// @notice capable of setting properties on Balancer BasePool utility wrapper + bytes32 internal constant BALANCER_MANAGER_ADMIN_ROLE = keccak256("BALANCER_MANAGER_ADMIN_ROLE"); + /*/////////////////////////////////////////////////////////////// Minor Roles //////////////////////////////////////////////////////////////*/ bytes32 internal constant POD_METADATA_REGISTER_ROLE = keccak256("POD_METADATA_REGISTER_ROLE"); - /// @notice capable of poking existing LBP auctions to exchange tokens. - bytes32 internal constant LBP_SWAP_ROLE = keccak256("SWAP_ADMIN_ROLE"); - /// @notice capable of engaging with Votium for voting incentives. bytes32 internal constant VOTIUM_ROLE = keccak256("VOTIUM_ADMIN_ROLE"); /// @notice capable of adding an address to multi rate limited bytes32 internal constant ADD_MINTER_ROLE = keccak256("ADD_MINTER_ROLE"); - /// @notice capable of changing parameters within non-critical ranges - bytes32 internal constant MINOR_PARAM_ROLE = keccak256("MINOR_PARAM_ROLE"); - /// @notice capable of changing PCV Deposit and Global Rate Limited Minter in the PSM bytes32 internal constant PSM_ADMIN_ROLE = keccak256("PSM_ADMIN_ROLE"); + + /// @notice capable of moving PCV between safe addresses on the PCVGuardian + bytes32 internal constant PCV_SAFE_MOVER_ROLE = keccak256("PCV_SAFE_MOVER_ROLE"); } diff --git a/contracts/pcv/PCVGuardian.sol b/contracts/pcv/PCVGuardian.sol index 9a32eee8d..497098656 100644 --- a/contracts/pcv/PCVGuardian.sol +++ b/contracts/pcv/PCVGuardian.sol @@ -6,6 +6,7 @@ import "../refs/CoreRef.sol"; import "./IPCVGuardian.sol"; import "./IPCVDeposit.sol"; import "../libs/CoreRefPauseableLib.sol"; +import {TribeRoles} from "../core/TribeRoles.sol"; contract PCVGuardian is IPCVGuardian, CoreRef { using CoreRefPauseableLib for address; @@ -15,8 +16,6 @@ contract PCVGuardian is IPCVGuardian, CoreRef { EnumerableSet.AddressSet private safeAddresses; constructor(address _core, address[] memory _safeAddresses) CoreRef(_core) { - _setContractAdminRole(keccak256("PCV_GUARDIAN_ADMIN_ROLE")); - for (uint256 i = 0; i < _safeAddresses.length; i++) { _setSafeAddress(_safeAddresses[i]); } @@ -35,34 +34,50 @@ contract PCVGuardian is IPCVGuardian, CoreRef { return safeAddresses.values(); } - // ---------- Governor-or-Admin-Only State-Changing API ---------- + // ---------- GOVERNOR-or-PCV_GUARDIAN_ADMIN-Only State-Changing API ---------- /// @notice governor-only method to set an address as "safe" to withdraw funds to /// @param pcvDeposit the address to set as safe - function setSafeAddress(address pcvDeposit) external override onlyGovernorOrAdmin { + function setSafeAddress(address pcvDeposit) + external + override + hasAnyOfTwoRoles(TribeRoles.GOVERNOR, TribeRoles.PCV_GUARDIAN_ADMIN) + { _setSafeAddress(pcvDeposit); } /// @notice batch version of setSafeAddress /// @param _safeAddresses the addresses to set as safe, as calldata - function setSafeAddresses(address[] calldata _safeAddresses) external override onlyGovernorOrAdmin { + function setSafeAddresses(address[] calldata _safeAddresses) + external + override + hasAnyOfTwoRoles(TribeRoles.GOVERNOR, TribeRoles.PCV_GUARDIAN_ADMIN) + { require(_safeAddresses.length != 0, "empty"); for (uint256 i = 0; i < _safeAddresses.length; i++) { _setSafeAddress(_safeAddresses[i]); } } - // ---------- Governor-or-Admin-Or-Guardian-Only State-Changing API ---------- + // ---------- GOVERNOR-or-PCV_GUARDIAN_ADMIN-Or-GUARDIAN-Only State-Changing API ---------- /// @notice governor-or-guardian-only method to un-set an address as "safe" to withdraw funds to /// @param pcvDeposit the address to un-set as safe - function unsetSafeAddress(address pcvDeposit) external override isGovernorOrGuardianOrAdmin { + function unsetSafeAddress(address pcvDeposit) + external + override + hasAnyOfThreeRoles(TribeRoles.GOVERNOR, TribeRoles.GUARDIAN, TribeRoles.PCV_GUARDIAN_ADMIN) + { _unsetSafeAddress(pcvDeposit); } /// @notice batch version of unsetSafeAddresses /// @param _safeAddresses the addresses to un-set as safe - function unsetSafeAddresses(address[] calldata _safeAddresses) external override isGovernorOrGuardianOrAdmin { + function unsetSafeAddresses(address[] calldata _safeAddresses) + external + override + hasAnyOfThreeRoles(TribeRoles.GOVERNOR, TribeRoles.GUARDIAN, TribeRoles.PCV_GUARDIAN_ADMIN) + { require(_safeAddresses.length != 0, "empty"); for (uint256 i = 0; i < _safeAddresses.length; i++) { _unsetSafeAddress(_safeAddresses[i]); @@ -81,7 +96,7 @@ contract PCVGuardian is IPCVGuardian, CoreRef { uint256 amount, bool pauseAfter, bool depositAfter - ) external override isGovernorOrGuardianOrAdmin { + ) external override hasAnyOfThreeRoles(TribeRoles.GOVERNOR, TribeRoles.PCV_SAFE_MOVER_ROLE, TribeRoles.GUARDIAN) { require(isSafeAddress(safeAddress), "Provided address is not a safe address!"); pcvDeposit._ensureUnpaused(); @@ -111,7 +126,7 @@ contract PCVGuardian is IPCVGuardian, CoreRef { uint256 amount, bool pauseAfter, bool depositAfter - ) external override isGovernorOrGuardianOrAdmin { + ) external override hasAnyOfThreeRoles(TribeRoles.GOVERNOR, TribeRoles.PCV_SAFE_MOVER_ROLE, TribeRoles.GUARDIAN) { require(isSafeAddress(safeAddress), "Provided address is not a safe address!"); pcvDeposit._ensureUnpaused(); @@ -142,7 +157,7 @@ contract PCVGuardian is IPCVGuardian, CoreRef { uint256 amount, bool pauseAfter, bool depositAfter - ) external override isGovernorOrGuardianOrAdmin { + ) external override hasAnyOfThreeRoles(TribeRoles.GOVERNOR, TribeRoles.PCV_SAFE_MOVER_ROLE, TribeRoles.GUARDIAN) { require(isSafeAddress(safeAddress), "Provided address is not a safe address!"); pcvDeposit._ensureUnpaused(); diff --git a/hardhat.config.ts b/hardhat.config.ts index 1831a6987..4790ea15f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -57,7 +57,7 @@ export default { forking: enableMainnetForking ? { url: `https://eth-mainnet.alchemyapi.io/v2/${mainnetAlchemyApiKey}`, - blockNumber: 14723389 // Friday, May 6th + blockNumber: 14807700 // Thursday, May 19th } : undefined }, diff --git a/package-lock.json b/package-lock.json index b2a02539e..6f9040ba1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "@typechain/hardhat": "^2.3.0", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.30", + "@types/node": "^17.0.31", "@typescript-eslint/eslint-plugin": "^4.31.2", "@typescript-eslint/parser": "^4.31.2", "chai-bn": "^0.3.1", @@ -49,10 +49,10 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.0.0", "ethereum-waffle": "^3.4.4", - "ethers": "^5.6.4", + "ethers": "^5.6.5", "husky": "^7.0.4", "lint-staged": "^12.4.1", - "mocha": "^9.2.2", + "mocha": "^10.0.0", "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "prettier": "^2.6.2", @@ -61,13 +61,13 @@ "solhint-plugin-prettier": "^0.0.5", "solidity-coverage": "^0.7.21", "ts-node": "^10.7.0", - "tsconfig-paths": "^3.14.1", + "tsconfig-paths": "^4.0.0", "typechain": "^5.2.0", "typescript": "^4.6.4" }, "engines": { "node": ">=16.0.0", - "npm": ">=8.0.0" + "npm": ">=8.0.1" } }, "node_modules/@babel/code-frame": { @@ -1266,9 +1266,9 @@ } }, "node_modules/@ethersproject/providers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", - "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.5.tgz", + "integrity": "sha512-TRS+c2Ud+cMpWodmGAc9xbnYRPWzRNYt2zkCSnj58nJoamBQ6x4cUbBeo0lTC3y+6RDVIBeJv18OqsDbSktLVg==", "funding": [ { "type": "individual", @@ -1360,9 +1360,9 @@ } }, "node_modules/@ethersproject/signing-key": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", - "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.1.tgz", + "integrity": "sha512-XvqQ20DH0D+bS3qlrrgh+axRMth5kD1xuvqUQUTeezxUTXBOeR6hWz2/C6FBEu39FRytyybIWrYf7YLSAKr1LQ==", "funding": [ { "type": "individual", @@ -4471,9 +4471,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.30.tgz", - "integrity": "sha512-oNBIZjIqyHYP8VCNAV9uEytXVeXG2oR0w9lgAXro20eugRQfY002qr3CUl6BAe+Yf/z3CRjPdz27Pu6WWtuSRw==" + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" }, "node_modules/@types/node-fetch": { "version": "2.6.1", @@ -7727,12 +7727,36 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/eslint-plugin-import/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", @@ -8899,9 +8923,9 @@ } }, "node_modules/ethers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", - "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.5.tgz", + "integrity": "sha512-9CTmplO9bv0s/aPw3HB3txGzKz3tUSI2EfO4dJo0W2WvaEq1ArgsEX6obV+bj5X3yY+Zgb1kAux8TDtJKe1FaA==", "funding": [ { "type": "individual", @@ -8931,11 +8955,11 @@ "@ethersproject/networks": "5.6.2", "@ethersproject/pbkdf2": "5.6.0", "@ethersproject/properties": "5.6.0", - "@ethersproject/providers": "5.6.4", + "@ethersproject/providers": "5.6.5", "@ethersproject/random": "5.6.0", "@ethersproject/rlp": "5.6.0", "@ethersproject/sha2": "5.6.0", - "@ethersproject/signing-key": "5.6.0", + "@ethersproject/signing-key": "5.6.1", "@ethersproject/solidity": "5.6.0", "@ethersproject/strings": "5.6.0", "@ethersproject/transactions": "5.6.0", @@ -18644,11 +18668,43 @@ "hardhat": "^2.0.2" } }, + "node_modules/hardhat/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/hardhat/node_modules/commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, + "node_modules/hardhat/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/hardhat/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/hardhat/node_modules/find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -18673,6 +18729,25 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/hardhat/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hardhat/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/hardhat/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -18693,6 +18768,140 @@ "node": ">=4" } }, + "node_modules/hardhat/node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hardhat/node_modules/mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/hardhat/node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hardhat/node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hardhat/node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/hardhat/node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hardhat/node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hardhat/node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hardhat/node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/hardhat/node_modules/p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -18819,6 +19028,20 @@ "semver": "bin/semver" } }, + "node_modules/hardhat/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/hardhat/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -18835,6 +19058,11 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/hardhat/node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -20118,15 +20346,15 @@ } }, "node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonfile": { @@ -21258,41 +21486,40 @@ } }, "node_modules/mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", + "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", - "debug": "4.3.3", + "debug": "4.3.4", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", - "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", - "minimatch": "4.2.1", + "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.1", + "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", + "workerpool": "6.2.1", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14.0.0" }, "funding": { "type": "opencollective", @@ -21370,33 +21597,23 @@ "node_modules/mocha/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -21408,6 +21625,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -21423,6 +21641,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -21431,6 +21650,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -21442,6 +21662,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -21453,11 +21674,12 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" @@ -21466,12 +21688,14 @@ "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -21486,6 +21710,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -21500,6 +21725,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -21689,9 +21915,10 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -27090,13 +27317,12 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz", + "integrity": "sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==", "dev": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^2.2.1", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -28181,9 +28407,10 @@ "dev": true }, "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -29401,9 +29628,9 @@ } }, "@ethersproject/providers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", - "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.5.tgz", + "integrity": "sha512-TRS+c2Ud+cMpWodmGAc9xbnYRPWzRNYt2zkCSnj58nJoamBQ6x4cUbBeo0lTC3y+6RDVIBeJv18OqsDbSktLVg==", "requires": { "@ethersproject/abstract-provider": "^5.6.0", "@ethersproject/abstract-signer": "^5.6.0", @@ -29455,9 +29682,9 @@ } }, "@ethersproject/signing-key": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", - "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.1.tgz", + "integrity": "sha512-XvqQ20DH0D+bS3qlrrgh+axRMth5kD1xuvqUQUTeezxUTXBOeR6hWz2/C6FBEu39FRytyybIWrYf7YLSAKr1LQ==", "requires": { "@ethersproject/bytes": "^5.6.0", "@ethersproject/logger": "^5.6.0", @@ -32163,9 +32390,9 @@ "dev": true }, "@types/node": { - "version": "17.0.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.30.tgz", - "integrity": "sha512-oNBIZjIqyHYP8VCNAV9uEytXVeXG2oR0w9lgAXro20eugRQfY002qr3CUl6BAe+Yf/z3CRjPdz27Pu6WWtuSRw==" + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", + "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" }, "@types/node-fetch": { "version": "2.6.1", @@ -34831,11 +35058,32 @@ "esutils": "^2.0.2" } }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } } } }, @@ -35677,9 +35925,9 @@ } }, "ethers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", - "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.5.tgz", + "integrity": "sha512-9CTmplO9bv0s/aPw3HB3txGzKz3tUSI2EfO4dJo0W2WvaEq1ArgsEX6obV+bj5X3yY+Zgb1kAux8TDtJKe1FaA==", "requires": { "@ethersproject/abi": "5.6.1", "@ethersproject/abstract-provider": "5.6.0", @@ -35699,11 +35947,11 @@ "@ethersproject/networks": "5.6.2", "@ethersproject/pbkdf2": "5.6.0", "@ethersproject/properties": "5.6.0", - "@ethersproject/providers": "5.6.4", + "@ethersproject/providers": "5.6.5", "@ethersproject/random": "5.6.0", "@ethersproject/rlp": "5.6.0", "@ethersproject/sha2": "5.6.0", - "@ethersproject/signing-key": "5.6.0", + "@ethersproject/signing-key": "5.6.1", "@ethersproject/solidity": "5.6.0", "@ethersproject/strings": "5.6.0", "@ethersproject/transactions": "5.6.0", @@ -42824,11 +43072,29 @@ "ws": "^7.4.6" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -42847,6 +43113,19 @@ "universalify": "^0.1.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -42864,6 +43143,95 @@ "path-exists": "^3.0.0" } }, + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + } + } + }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -42959,6 +43327,14 @@ } } }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -42968,6 +43344,11 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" } } }, @@ -44067,13 +44448,10 @@ } }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true }, "jsonfile": { "version": "6.1.0", @@ -44958,31 +45336,30 @@ } }, "mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", + "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", - "debug": "4.3.3", + "debug": "4.3.4", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", - "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", - "minimatch": "4.2.1", + "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.1", + "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", + "workerpool": "6.2.1", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -44991,32 +45368,29 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } + "balanced-match": "^1.0.0" } }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -45025,12 +45399,14 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "requires": { "argparse": "^2.0.1" } @@ -45039,27 +45415,31 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "requires": { "p-locate": "^5.0.0" } }, "minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" } }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "requires": { "yocto-queue": "^0.1.0" } @@ -45068,6 +45448,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "requires": { "p-limit": "^3.0.2" } @@ -45076,6 +45457,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -45296,9 +45678,10 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true }, "nanomatch": { "version": "1.2.13", @@ -49469,13 +49852,12 @@ } }, "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz", + "integrity": "sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==", "dev": true, "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^2.2.1", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -50380,9 +50762,10 @@ "dev": true }, "workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "wrap-ansi": { "version": "7.0.0", diff --git a/package.json b/package.json index 282584c1c..08350784e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "console:ropsten": "npx hardhat console --network ropsten", "clean": "forge clean && rm -rf artifacts", "test": "forge test --no-match-contract IntegrationTest", - "test:integration": "FORK_BLOCK=14516592; forge test --fork-url https://eth-mainnet.alchemyapi.io/v2/$MAINNET_ALCHEMY_API_KEY --fork-block-number $FORK_BLOCK --match-contract IntegrationTest", + "test:integration": "FORK_BLOCK=14810964; forge test --fork-url https://eth-mainnet.alchemyapi.io/v2/$MAINNET_ALCHEMY_API_KEY --fork-block-number $FORK_BLOCK --match-contract IntegrationTest", "test:integration:latest": "forge test --fork-url https://eth-mainnet.alchemyapi.io/v2/$MAINNET_ALCHEMY_API_KEY --match-contract IntegrationTest", "test:hardhat": "npx hardhat test", "test:hardhat:dependencies": "LOGGING=true NO_RESET=true npx hardhat test test/integration/tests/dependencies.ts", @@ -45,7 +45,7 @@ "author": "joeysantoro", "license": "AGPL-3.0-only", "engines": { - "npm": ">=8.0.0", + "npm": ">=8.0.1", "node": ">=16.0.0" }, "dependencies": { @@ -79,7 +79,7 @@ "@typechain/hardhat": "^2.3.0", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.30", + "@types/node": "^17.0.31", "@typescript-eslint/eslint-plugin": "^4.31.2", "@typescript-eslint/parser": "^4.31.2", "chai-bn": "^0.3.1", @@ -89,10 +89,10 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.0.0", "ethereum-waffle": "^3.4.4", - "ethers": "^5.6.4", + "ethers": "^5.6.5", "husky": "^7.0.4", "lint-staged": "^12.4.1", - "mocha": "^9.2.2", + "mocha": "^10.0.0", "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "prettier": "^2.6.2", @@ -101,7 +101,7 @@ "solhint-plugin-prettier": "^0.0.5", "solidity-coverage": "^0.7.21", "ts-node": "^10.7.0", - "tsconfig-paths": "^3.14.1", + "tsconfig-paths": "^4.0.0", "typechain": "^5.2.0", "typescript": "^4.6.4" }, diff --git a/proposals/dao/fip_82b.ts b/proposals/dao/fip_82b.ts new file mode 100644 index 000000000..24ffee305 --- /dev/null +++ b/proposals/dao/fip_82b.ts @@ -0,0 +1,191 @@ +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { + DeployUpgradeFunc, + NamedAddresses, + NamedContracts, + SetupUpgradeFunc, + TeardownUpgradeFunc, + ValidateUpgradeFunc +} from '@custom-types/types'; +import { Contract } from 'ethers'; +import { validateArraysEqual } from '@test/helpers'; + +/* + +DAO Proposal fip_82b + +Description: +1. Transfer admin of non-major TribeRoles to ROLE_ADMIN, to allow the TribalCouncil to grant out +2. Create several new TribeRoles for management of the protocol, with the ROLE_ADMIN as their admin +3. Transfer contract admins of various contracts to these new roles +4. Grant the TribalCouncil the various roles it needs to run the protocol +*/ + +const fipNumber = 'fip_82b'; + +// Do any deployments +// This should exclusively include new contract deployments +const deploy: DeployUpgradeFunc = async (deployAddress: string, addresses: NamedAddresses, logging: boolean) => { + const deploySigner = (await ethers.getSigners())[0]; + const previousPCVGuardian = await ethers.getContractAt('PCVGuardian', addresses.pcvGuardian, deploySigner); + const safeAddresses = await previousPCVGuardian.getSafeAddresses(); + + const pcvGuardianFactory = await ethers.getContractFactory('PCVGuardian'); + const pcvGuardianNew = await pcvGuardianFactory.deploy(addresses.core, safeAddresses); + logging && console.log('PCVGuardian deployed to: ', pcvGuardianNew.address); + logging && console.log('PCVGuardian safeAddresses: ', safeAddresses); + + return { + pcvGuardianNew + }; +}; + +// Do any setup necessary for running the test. +// This could include setting up Hardhat to impersonate accounts, +// ensuring contracts have a specific state, etc. +const setup: SetupUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + console.log(`No actions to complete in setup for fip${fipNumber}`); +}; + +// Tears down any changes made in setup() that need to be +// cleaned up before doing any validation checks. +const teardown: TeardownUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + console.log(`No actions to complete in teardown for fip${fipNumber}`); +}; + +// Run any validations required on the fip using mocha or console logging +// IE check balances, check state of contracts, etc. +const validate: ValidateUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + // 1. Validate new PCVGuardian deployment and roles granted + const core = contracts.core; + const newPCVGuardian = contracts.pcvGuardianNew; + + const safeAddresses = await newPCVGuardian.getSafeAddresses(); + const expectedSafeAddresses = [ + '0xd51dba7a94e1adea403553a8235c302cebf41a3c', + '0x4fcb1435fd42ce7ce7af3cb2e98289f79d2962b3', + '0x98e5f5706897074a4664dd3a32eb80242d6e694b', + '0x5b86887e171bae0c2c826e87e34df8d558c079b9', + '0x2a188f9eb761f70ecea083ba6c2a40145078dfc2', + '0xb0e731f036adfdec12da77c15aab0f90e8e45a0e', + '0x24f663c69cd4b263cf5685a49013ff5f1c898d24', + '0x5ae217de26f6ff5f481c6e10ec48b2cf2fc857c8', + '0xe8633c49ace655eb4a8b720e6b12f09bd3a97812', + '0xcd1ac0014e2ebd972f40f24df1694e6f528b2fd4', + '0xc5bb8f0253776bec6ff450c2b40f092f7e7f5b57', + '0xc4eac760c2c631ee0b064e39888b89158ff808b2', + '0x2c47fef515d2c70f2427706999e158533f7cf090', + '0x9aadffe00eae6d8e59bb4f7787c6b99388a6960d', + '0xd2174d78637a40448112aa6b30f9b19e6cf9d1f9', + '0x5dde9b4b14edf59cb23c1d4579b279846998205e' + ]; + validateArraysEqual(safeAddresses, expectedSafeAddresses); + + // New PCV Guardian roles - validate granted + expect(await core.hasRole(ethers.utils.id('GUARDIAN_ROLE'), newPCVGuardian.address)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PCV_CONTROLLER_ROLE'), newPCVGuardian.address)).to.be.true; + + // Old PCV Guardian roles - validate revoked + expect(await core.hasRole(ethers.utils.id('GUARDIAN_ROLE'), addresses.pcvGuardian)).to.be.false; + expect(await core.hasRole(ethers.utils.id('PCV_CONTROLLER_ROLE'), addresses.pcvGuardian)).to.be.false; + + // 2. Validate TribalCouncil role transfers + await validateTransferredRoleAdmins(contracts.core); + await validateNewCouncilRoles(contracts.core); + await validateContractAdmins(contracts); + await validateTribalCouncilRoles(contracts.core, addresses.tribalCouncilTimelock); + await validateCallingContractsHaveNewAdmin(contracts.core, addresses); +}; + +/// Validate that all non-major TribeRoles have had their admins transferred to the ROLE_ADMIN +const validateTransferredRoleAdmins = async (core: Contract) => { + const ROLE_ADMIN = ethers.utils.id('ROLE_ADMIN'); + + // Non-major roles that previously had 0x0 as their admin + expect(await core.getRoleAdmin(ethers.utils.id('RATE_LIMITED_MINTER_ADMIN'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PARAMETER_ADMIN'))).to.be.equal(ROLE_ADMIN); + + // Non-major roles that previously had GOVERNOR as their admin + expect(await core.getRoleAdmin(ethers.utils.id('ORACLE_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('TRIBAL_CHIEF_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PCV_GUARDIAN_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('METAGOVERNANCE_VOTE_ADMIN'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('METAGOVERNANCE_TOKEN_STAKING'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('METAGOVERNANCE_GAUGE_ADMIN'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('SWAP_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('VOTIUM_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('RATE_LIMITED_MINTER_ADMIN'))).to.be.equal(ROLE_ADMIN); + + expect(await core.getRoleAdmin(ethers.utils.id('BALANCER_MANAGER_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('SWAP_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); +}; + +/// Validate that the expected new TribeRoles have been created +const validateNewCouncilRoles = async (core: Contract) => { + const ROLE_ADMIN = ethers.utils.id('ROLE_ADMIN'); + + expect(await core.getRoleAdmin(ethers.utils.id('FUSE_ADMIN'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('FEI_MINT_ADMIN'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PCV_MINOR_PARAM_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PSM_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PCV_SAFE_MOVER_ROLE'))).to.be.equal(ROLE_ADMIN); + expect(await core.getRoleAdmin(ethers.utils.id('PCV_GUARDIAN_ADMIN_ROLE'))).to.be.equal(ROLE_ADMIN); +}; + +/// Validate that the relevant contract admins have been set to their expected values +const validateContractAdmins = async (contracts: NamedContracts) => { + expect(await contracts.fuseGuardian.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('FUSE_ADMIN')); + + expect(await contracts.optimisticMinter.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('FEI_MINT_ADMIN')); + expect(await contracts.pcvEquityMinter.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('FEI_MINT_ADMIN')); + expect(await contracts.indexDelegator.CONTRACT_ADMIN_ROLE()).to.be.equal( + ethers.utils.id('METAGOVERNANCE_VOTE_ADMIN') + ); + expect(await contracts.ethTokemakPCVDeposit.CONTRACT_ADMIN_ROLE()).to.be.equal( + ethers.utils.id('TOKEMAK_DEPOSIT_ADMIN_ROLE') + ); + expect(await contracts.uniswapPCVDeposit.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('PCV_MINOR_PARAM_ROLE')); + + expect(await contracts.lusdPSMFeiSkimmer.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('PCV_MINOR_PARAM_ROLE')); + expect(await contracts.ethPSMFeiSkimmer.CONTRACT_ADMIN_ROLE()).to.be.equal(ethers.utils.id('PCV_MINOR_PARAM_ROLE')); + + expect(await contracts.aaveEthPCVDripController.CONTRACT_ADMIN_ROLE()).to.be.equal( + ethers.utils.id('PCV_MINOR_PARAM_ROLE') + ); + expect(await contracts.daiPCVDripController.CONTRACT_ADMIN_ROLE()).to.be.equal( + ethers.utils.id('PCV_MINOR_PARAM_ROLE') + ); + expect(await contracts.lusdPCVDripController.CONTRACT_ADMIN_ROLE()).to.be.equal( + ethers.utils.id('PCV_MINOR_PARAM_ROLE') + ); +}; + +const validateCallingContractsHaveNewAdmin = async (core: Contract, addresses: NamedAddresses) => { + // TRIBAL_CHIEF_ADMIN_ROLE : FUSE_ADMIN + expect(await core.hasRole(ethers.utils.id('FUSE_ADMIN'), addresses.optimisticTimelock)).to.be.true; + expect(await core.hasRole(ethers.utils.id('FUSE_ADMIN'), addresses.tribalChiefSyncV2)).to.be.true; + + // GOVERNOR : FEI_MINT_ADMIN + expect(await core.hasRole(ethers.utils.id('FEI_MINT_ADMIN'), addresses.feiDAOTimelock)).to.be.true; + + // GOVERNOR : PCV_MINOR_PARAM_ROLE + expect(await core.hasRole(ethers.utils.id('PCV_MINOR_PARAM_ROLE'), addresses.feiDAOTimelock)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PCV_MINOR_PARAM_ROLE'), addresses.optimisticTimelock)).to.be.true; + + expect(await core.hasRole(ethers.utils.id('TOKEMAK_DEPOSIT_ADMIN_ROLE'), addresses.optimisticTimelock)).to.be.true; + expect(await core.hasRole(ethers.utils.id('TOKEMAK_DEPOSIT_ADMIN_ROLE'), addresses.feiDAOTimelock)).to.be.true; +}; + +const validateTribalCouncilRoles = async (core: Contract, tribalCouncilTimelockAddress: string) => { + expect(await core.hasRole(ethers.utils.id('FUSE_ADMIN'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('FEI_MINT_ADMIN'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PCV_MINOR_PARAM_ROLE'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PCV_GUARDIAN_ADMIN_ROLE'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('ORACLE_ADMIN_ROLE'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PSM_ADMIN_ROLE'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('PCV_SAFE_MOVER_ROLE'), tribalCouncilTimelockAddress)).to.be.true; + expect(await core.hasRole(ethers.utils.id('TOKEMAK_DEPOSIT_ADMIN_ROLE'), tribalCouncilTimelockAddress)).to.be.true; +}; + +export { deploy, setup, teardown, validate }; diff --git a/proposals/dao/old/fip_82.ts b/proposals/dao/old/fip_82.ts index 96202934a..2fb653ab1 100644 --- a/proposals/dao/old/fip_82.ts +++ b/proposals/dao/old/fip_82.ts @@ -7,18 +7,14 @@ import { TeardownUpgradeFunc, ValidateUpgradeFunc } from '@custom-types/types'; -import { getImpersonatedSigner } from '@test/helpers'; +import { getImpersonatedSigner, validateArraysEqual } from '@test/helpers'; import { tribeCouncilPodConfig, PodCreationConfig } from '@protocol/optimisticGovernance'; import { abi as inviteTokenABI } from '../../artifacts/@orcaprotocol/contracts/contracts/InviteToken.sol/InviteToken.json'; import { abi as timelockABI } from '../../artifacts/@openzeppelin/contracts/governance/TimelockController.sol/TimelockController.json'; import { abi as gnosisSafeABI } from '../../artifacts/contracts/pods/interfaces/IGnosisSafe.sol/IGnosisSafe.json'; -import { Contract, Signer } from 'ethers'; +import { Contract } from 'ethers'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -const validateArraysEqual = (arrayA: string[], arrayB: string[]) => { - arrayA.every((a) => expect(arrayB.map((b) => b.toLowerCase()).includes(a.toLowerCase()))); -}; - // Transfers Orca tokens from deployer address to the factory, so that it can deploy pods // Requirement of holding Orca tokens to deploy is a slow rollout mechanism used by Orca const transferOrcaTokens = async ( @@ -178,7 +174,7 @@ const validate: ValidateUpgradeFunc = async (addresses, oldContracts, contracts, const isProposalRegistered = await governanceMetadataRegistry.isProposalRegistered(0, 0, 'test'); expect(isProposalRegistered).to.be.false; - await validateTribeRoles( + await validateContractRoles( contracts.core, addresses.feiDAOTimelock, addresses.tribalCouncilTimelock, @@ -190,7 +186,7 @@ const validate: ValidateUpgradeFunc = async (addresses, oldContracts, contracts, }; // Validate that the relevant timelocks and Safes have the relevant TribeRoles -const validateTribeRoles = async ( +const validateContractRoles = async ( core: Contract, feiDAOTimelockAddress: string, tribalCouncilTimelockAddress: string, diff --git a/proposals/description/fip_82b.ts b/proposals/description/fip_82b.ts new file mode 100644 index 000000000..d118b4a3b --- /dev/null +++ b/proposals/description/fip_82b.ts @@ -0,0 +1,486 @@ +import { ProposalDescription } from '@custom-types/types'; + +const fip_82b: ProposalDescription = { + title: 'FIP-82b: Authorise the TribalCouncil with necessary roles', + commands: [ + /////// Transfer all non-major role admins to the ROLE_ADMIN, to allow TribalCouncil to manage //////// + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xf0b50f04623eeaacfa1f202e062a3001c925a35c6b75d6903e67b43f44bbf152', // PARAMETER_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer PARAMETER_ADMIN role admin to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xdc81827f5af6c7965785d62c38ca3481ccf540d7f561cac825518e49d6161c95', // RATE_LIMITED_MINTER_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer RATE_LIMITED_MINTER_ADMIN role admin to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xc307c44629779eb8fc0b85f224c3d22f5876a6c84de0ee42d481eb7814f0d3a8', // ORACLE_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer ORACLE_ADMIN_ROLE role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x2ed79c21cc719d0c08e90d592e29828e4bd23efdb9ac45a4fe9b6c0ab5955b80', // BALANCER_MANAGER_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer BALANCER_MANAGER_ADMIN_ROLE role admin to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x23970cab3799b6876df4319661e6c03cc45bd59628799d92e988dd8cbdc90e31', // TRIBAL_CHIEF_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer TRIBAL_CHIEF_ADMIN role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xdf6ce05acd28d71e96472375ef55c4a692f167af3ccda9500570f7373c1ba22c', // PCV_GUARDIAN_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer PCV_GUARDIAN_ADMIN_ROLE role from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xb02f76effb323167cad756bb4f3edbfb9d9291f9bfcdc72c9ceea005562f32eb', // METAGOVERNANCE_VOTE_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer METAGOVERNANCE_VOTE_ADMIN role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xa100760f521bbb2848bef0b72ea29301f6a6b0605d004243f0eea2b1c359f7c7', // METAGOVERNANCE_TOKEN_STAKING + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer METAGOVERNANCE_TOKEN_STAKING role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x3bee38c33241595abfefa470fd75bfa1cc9cb01eff02cf6732fd2baea4ea4241', // METAGOVERNANCE_GAUGE_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer METAGOVERNANCE_GAUGE_ADMIN role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x471cfe1a44bf1b786db7d7104d51e6728ed7b90a35394ad7cc424adf8ed16816', // SWAP_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer SWAP_ADMIN_ROLE role admin from GOVERNOR to ROLE_ADMIN' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x2d46c62aa6fbc9b550f22e00476aebb90f4ea69cd492a68db4d444217763330d', // VOTIUM_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Transfer VOTIUM_ROLE role admin from GOVERNOR to ROLE_ADMIN' + }, + //////// Create new roles for the Tribal Council to manage ///////// + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x7f85477db6c0857f19179a2b3846a7ddbc64caeeb3a02ef34771b82f5ab926e4', // FUSE_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Create FUSE_ADMIN role, assigning ROLE_ADMIN as the role admin' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x4a4f013dcba6b46103e81e286782135c0dda175e82564e878ae500734753e55e', // FEI_MINT_ADMIN + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Create FEI_MINT_ADMIN role, assigning ROLE_ADMIN as the role admin' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed', // PCV_MINOR_PARAM_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Create PCV_MINOR_PARAM_ROLE role, assigning ROLE_ADMIN as the role admin' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0x1749ca1ca3564d20da6efea465c2a5ae869a9e4b006da7035e688beb14d704e0', // PSM_ADMIN_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Create PSM_ADMIN_ROLE role, assigning ROLE_ADMIN as the role admin' + }, + { + target: 'core', + values: '0', + method: 'createRole(bytes32,bytes32)', + arguments: [ + '0xd387c7eec7161b3637e694ef5cf8f1a9e29bfd35135c86c9b540bebec4ef221a', // PCV_SAFE_MOVER_ROLE + '0x2172861495e7b85edac73e3cd5fbb42dd675baadf627720e687bcfdaca025096' // ROLE_ADMIN + ], + description: 'Create PCV_SAFE_MOVER_ROLE role, assigning ROLE_ADMIN as the role admin' + }, + /////// Set the relevant contract admins to the newly created roles ////////// + // FUSE_ADMIN + { + target: 'fuseGuardian', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x7f85477db6c0857f19179a2b3846a7ddbc64caeeb3a02ef34771b82f5ab926e4' // FUSE_ADMIN + ], + description: 'Set the contract admin of the FuseGuardian to be the FUSE_ADMIN' + }, + // FEI_MINT_ADMIN + { + target: 'optimisticMinter', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x4a4f013dcba6b46103e81e286782135c0dda175e82564e878ae500734753e55e' // FEI_MINT_ADMIN + ], + description: 'Set the contract admin of the FeiTimedMinter to be the FEI_MINT_ADMIN' + }, + { + target: 'pcvEquityMinter', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x4a4f013dcba6b46103e81e286782135c0dda175e82564e878ae500734753e55e' // FEI_MINT_ADMIN + ], + description: 'Set the contract admin of the PCV Equity Minter to be the FEI_MINT_ADMIN' + }, + { + target: 'ethTokemakPCVDeposit', // TokemakPCVDepositBase + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x6c9ecf07a5886fd74a8d32f4d3c317a7d5e5b5c7a073a3ab06c217e9ce5288e3' // TOKEMAK_DEPOSIT_ADMIN_ROLE + ], + description: 'Set the contract admin of the ethTokemarkPCVdeposit to be the TOKEMAK_DEPOSIT_ADMIN_ROLE' + }, + { + target: 'uniswapPCVDeposit', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the uniswapPCVDeposit to be the PCV_MINOR_PARAM_ROLE' + }, + { + target: 'lusdPSMFeiSkimmer', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the LUSD PSM Fei Skimmer to be the PCV_MINOR_PARAM_ROLE' + }, + { + target: 'ethPSMFeiSkimmer', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the ETH PSM Fei Skimmer to be the PCV_MINOR_PARAM_ROLE' + }, + { + target: 'aaveEthPCVDripController', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the Aave Eth PCV Drip Controller to be the PCV_MINOR_PARAM_ROLE' + }, + { + target: 'daiPCVDripController', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the DAI PCV Drip Controller to be the PCV_MINOR_PARAM_ROLE' + }, + { + target: 'lusdPCVDripController', + values: '0', + method: 'setContractAdminRole(bytes32)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed' // PCV_MINOR_PARAM_ROLE + ], + description: 'Set the contract admin of the LUSDC PCV Drip Controller to be the PCV_MINOR_PARAM_ROLE' + }, + ////////// Grant the Tribal Council timelock the relevant roles ////////// + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x7f85477db6c0857f19179a2b3846a7ddbc64caeeb3a02ef34771b82f5ab926e4', // FUSE_ADMIN + '{tribalCouncilTimelock}' + ], + description: 'Grant TribalCouncil timelock the FUSE_ADMIN role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0xb02f76effb323167cad756bb4f3edbfb9d9291f9bfcdc72c9ceea005562f32eb', // METAGOVERNANCE_VOTE_ADMIN + '{tribalCouncilTimelock}' + ], + description: 'Grant METAGOVERNANCE_VOTE_ADMIN to the tribalCouncilTimelock' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x6c9ecf07a5886fd74a8d32f4d3c317a7d5e5b5c7a073a3ab06c217e9ce5288e3', // TOKEMAK_DEPOSIT_ADMIN_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant TOKEMAK_DEPOSIT_ADMIN_ROLE to the tribalCouncilTimelock' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x6c9ecf07a5886fd74a8d32f4d3c317a7d5e5b5c7a073a3ab06c217e9ce5288e3', // TOKEMAK_DEPOSIT_ADMIN_ROLE + '{feiDAOTimelock}' + ], + description: 'Grant TOKEMAK_DEPOSIT_ADMIN_ROLE to the feiDAOTimelock' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x4a4f013dcba6b46103e81e286782135c0dda175e82564e878ae500734753e55e', // FEI_MINT_ADMIN + '{tribalCouncilTimelock}' + ], + description: 'Grant TribalCouncil timelock the FEI_MINT_ADMIN role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed', // PCV_MINOR_PARAM_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant TribalCouncil timelock the PCV_MINOR_PARAM_ROLE role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0xc307c44629779eb8fc0b85f224c3d22f5876a6c84de0ee42d481eb7814f0d3a8', // ORACLE_ADMIN_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant TribalCouncil timelock the ORACLE_ADMIN_ROLE' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x1749ca1ca3564d20da6efea465c2a5ae869a9e4b006da7035e688beb14d704e0', // PSM_ADMIN_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant TribalCouncil timelock the PSM_ADMIN_ROLE' + }, + //////// Grant contract admin calling contracts the new roles ///////// + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed', // PCV_MINOR_PARAM_ROLE + '{feiDAOTimelock}' + ], + description: 'Grant feiDAOtimelock the PCV_MINOR_PARAM_ROLE role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x46797b318ce8c2d83979760ef100a5c0fdb980de4b574d6142ce4d0afce307ed', // PCV_MINOR_PARAM_ROLE + '{optimisticTimelock}' + ], + description: 'Grant optimisticTimelock the PCV_MINOR_PARAM_ROLE role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x7f85477db6c0857f19179a2b3846a7ddbc64caeeb3a02ef34771b82f5ab926e4', // FUSE_ADMIN + '{optimisticTimelock}' + ], + description: 'Grant optimistic timelock the FUSE_ADMIN role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x7f85477db6c0857f19179a2b3846a7ddbc64caeeb3a02ef34771b82f5ab926e4', // FUSE_ADMIN + '{tribalChiefSyncV2}' + ], + description: 'Grant tribalChiefSyncV2 the FUSE_ADMIN role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x4a4f013dcba6b46103e81e286782135c0dda175e82564e878ae500734753e55e', // FEI_MINT_ADMIN + '{feiDAOTimelock}' + ], + description: 'Grant feiDAOTimelock the FEI_MINT_ADMIN role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x6c9ecf07a5886fd74a8d32f4d3c317a7d5e5b5c7a073a3ab06c217e9ce5288e3', // TOKEMAK_DEPOSIT_ADMIN_ROLE + '{optimisticTimelock}' + ], + description: 'Grant optimisticTimelock the TOKEMAK_DEPOSIT_ADMIN_ROLE role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0xd387c7eec7161b3637e694ef5cf8f1a9e29bfd35135c86c9b540bebec4ef221a', // PCV_SAFE_MOVER_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant tribalCouncilTimelock the PCV_SAFE_MOVER_ROLE role' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0xdf6ce05acd28d71e96472375ef55c4a692f167af3ccda9500570f7373c1ba22c', // PCV_GUARDIAN_ADMIN_ROLE + '{tribalCouncilTimelock}' + ], + description: 'Grant tribalCouncilTimelock the PCV_GUARDIAN_ADMIN_ROLE role' + }, + ////// Authorise new PCV Guardian and revoke old PCV Guardian //////// + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x0866eae1216ed05a11636a648003f3f62921eb97ccb05acc30636f62958a8bd6', // PCV_CONTROLLER + '{pcvGuardianNew}' + ], + description: 'Grant newPCVGuardian the PCV_CONTROLLER_ROLE' + }, + { + target: 'core', + values: '0', + method: 'grantRole(bytes32,address)', + arguments: [ + '0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041', // GUARDIAN + '{pcvGuardianNew}' + ], + description: 'Grant newPCVGuardian the GUARDIAN role' + }, + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: [ + '0x0866eae1216ed05a11636a648003f3f62921eb97ccb05acc30636f62958a8bd6', // PCV_CONTROLLER + '{pcvGuardian}' + ], + description: 'Revoke PCV_CONTROLLER from old pcvGuardian' + }, + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: [ + '0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041', // GUARDIAN + '{pcvGuardian}' + ], + description: 'Revoke GUARDIAN from old pcvGuardian' + } + ], + description: ` + FIP_82b: Authorise the TribalCouncil with necessary protocol roles + + This is the second stage of the Tribe DAO Governance upgrade. Overall, this proposal prepares the + TribalCouncil and optimistic governance pods system to operate the protocol in an optimistic fashion. + + Specifically, the proposal: + 1. Creates various new operational roles which the TribalCouncil will hold + 2. Transfers the admin of all non-major roles to the TribalCouncil (all major roles remain under the control of the DAO) + 3. Makes the TribalCouncil the admin of various operational smart contracts + 4. Creates a new PCVGuardian with a modern, more secure access control pattern + + The governance upgrade discussed and authorised by the following forum post and snapshot vote: + - Forum: https://tribe.fei.money/t/fip-82-governance-enhancements/3945 + - Snapshot vote: https://snapshot.fei.money/#/proposal/0x463fd1be98d9e86c83eb845ca7e2a5555387e3c86ca0b756aada17a11df87f2b + + The executable code associated with this proposal is available here: + - https://github.com/fei-protocol/fei-protocol-core/pull/678 + ` +}; + +export default fip_82b; diff --git a/protocol-configuration/collateralizationOracle.ts b/protocol-configuration/collateralizationOracle.ts index 94dc4861a..e748be1be 100644 --- a/protocol-configuration/collateralizationOracle.ts +++ b/protocol-configuration/collateralizationOracle.ts @@ -1,14 +1,10 @@ const collateralizationAddresses = { fei: [ 'feiOATimelockWrapper', - 'rariPool8FeiPCVDepositWrapper', 'rariPool6FeiPCVDepositWrapper', 'rariPool19FeiPCVDepositWrapper', 'rariPool24FeiPCVDepositWrapper', 'rariPool25FeiPCVDepositWrapper', - 'rariPool27FeiPCVDepositWrapper', - 'rariPool18FeiPCVDepositWrapper', - 'rariPool90FeiPCVDepositWrapper', 'aaveFeiPCVDepositWrapper', 'rariPool79FeiPCVDepositWrapper', 'rariPool31FeiPCVDepositWrapper', @@ -16,18 +12,11 @@ const collateralizationAddresses = { 'rariPool128FeiPCVDepositWrapper', 'rariPool22FeiPCVDepositWrapper', 'feiBuybackLensNoFee', - 'convexPoolPCVDepositWrapper', - 'compoundPCVDepositWrapper', + 'compoundFeiPCVDepositWrapper', 'turboFusePCVDeposit' ], - lusd: [ - 'liquityFusePoolLusdPCVDeposit', - 'rariPool7LusdPCVDeposit', - 'bammDeposit', - 'lusdPSM', - 'rariPool8LusdPCVDeposit' - ], - dai: ['compoundDaiPCVDepositWrapper', 'daiFixedPricePSM', 'rariPool8DaiPCVDeposit'], + lusd: ['liquityFusePoolLusdPCVDeposit', 'rariPool7LusdPCVDeposit', 'bammDeposit', 'lusdPSM'], + dai: ['compoundDaiPCVDepositWrapper', 'daiFixedPricePSM'], usd: ['namedStaticPCVDepositWrapper', 'd3poolCurvePCVDeposit', 'd3poolConvexPCVDeposit'], bal: ['balancerDepositBalWeth', 'balancerLensVeBalBal'], cream: ['creamDepositWrapper'], @@ -38,7 +27,6 @@ const collateralizationAddresses = { 'uniswapPCVDeposit', 'ethTokemakPCVDeposit', 'ethPSM', - 'rariPool146EthPCVDeposit', 'wethDepositWrapper', 'balancerDepositFeiWeth', 'balancerLensBpt30Fei70Weth', diff --git a/protocol-configuration/dependencies.ts b/protocol-configuration/dependencies.ts index 3c6bf9092..95e70277b 100644 --- a/protocol-configuration/dependencies.ts +++ b/protocol-configuration/dependencies.ts @@ -37,7 +37,7 @@ const dependencies: DependencyMap = { 'feiTribeLBPSwapper', 'optimisticMinter', 'pcvEquityMinter', - 'pcvGuardian', + 'pcvGuardianNew', 'ratioPCVControllerV2', 'tribe', 'tribeMinter', @@ -195,7 +195,7 @@ const dependencies: DependencyMap = { pcvEquityMinter: { contractDependencies: ['core', 'collateralizationOracleWrapper', 'feiTribeLBPSwapper'] }, - pcvGuardian: { + pcvGuardianNew: { contractDependencies: [ 'core', 'guardian', @@ -210,7 +210,7 @@ const dependencies: DependencyMap = { ] }, raiPriceBoundPSM: { - contractDependencies: ['core', 'fei', 'raiPCVDripController', 'pcvGuardian'] + contractDependencies: ['core', 'fei', 'raiPCVDripController', 'pcvGuardianNew'] }, proxyAdmin: { contractDependencies: [ @@ -261,14 +261,14 @@ const dependencies: DependencyMap = { 'aaveTribeIncentivesController', 'tribeMinter', 'timelock', - 'pcvGuardian', + 'pcvGuardianNew', 'pegExchanger', 'voltFeiSwapContract', 'voltDepositWrapper' ] }, guardian: { - contractDependencies: ['core', 'collateralizationOracleGuardian', 'pcvGuardian', 'fuseGuardian', 'fuseAdmin'] + contractDependencies: ['core', 'collateralizationOracleGuardian', 'pcvGuardianNew', 'fuseGuardian', 'fuseAdmin'] }, optimisticMultisig: { contractDependencies: ['optimisticTimelock'] @@ -313,7 +313,7 @@ const dependencies: DependencyMap = { 'compoundDaiPCVDeposit', 'daiPCVDripController', 'chainlinkDaiUsdOracleWrapper', - 'pcvGuardian' + 'pcvGuardianNew' ] }, lusdPSM: { @@ -322,7 +322,7 @@ const dependencies: DependencyMap = { 'fei', 'bammDeposit', 'chainlinkLUSDOracleWrapper', - 'pcvGuardian', + 'pcvGuardianNew', 'lusdPCVDripController', 'lusdPSMFeiSkimmer' ] @@ -339,7 +339,7 @@ const dependencies: DependencyMap = { 'fei', 'aaveEthPCVDeposit', 'chainlinkEthUsdOracleWrapper', - 'pcvGuardian', + 'pcvGuardianNew', 'aaveEthPCVDripController', 'ethPSMRouter', 'ethPSMFeiSkimmer' @@ -352,13 +352,13 @@ const dependencies: DependencyMap = { contractDependencies: ['core', 'tribeUsdCompositeOracle', 'tribeMinter', 'collateralizationOracleWrapper', 'tribe'] }, aaveEthPCVDeposit: { - contractDependencies: ['core', 'aaveEthPCVDripController', 'pcvGuardian', 'ethPSM'] + contractDependencies: ['core', 'aaveEthPCVDripController', 'pcvGuardianNew', 'ethPSM'] }, aaveFeiPCVDeposit: { contractDependencies: ['core', 'fei'] }, aaveRaiPCVDeposit: { - contractDependencies: ['core', 'pcvGuardian', 'raiPCVDripController'] + contractDependencies: ['core', 'pcvGuardianNew', 'raiPCVDripController'] }, agEurAngleUniswapPCVDeposit: { contractDependencies: ['core', 'fei', 'chainlinkEurUsdOracleWrapper'] @@ -373,7 +373,7 @@ const dependencies: DependencyMap = { contractDependencies: ['core', 'daiPCVDripController', 'daiFixedPricePSM'] }, compoundEthPCVDeposit: { - contractDependencies: ['core', 'pcvGuardian'] + contractDependencies: ['core', 'pcvGuardianNew'] }, d3poolConvexPCVDeposit: { contractDependencies: ['core'] @@ -656,6 +656,9 @@ const dependencies: DependencyMap = { 'balancerLensVeBalWeth' ] }, + balancerLensVeBalBal: { + contractDependencies: ['balUsdCompositeOracle', 'chainlinkEthUsdOracleWrapper'] + }, chainlinkBALEthOracle: { contractDependencies: ['core', 'balUsdCompositeOracle'] }, @@ -1017,18 +1020,6 @@ const dependencies: DependencyMap = { timelock: { contractDependencies: ['feiDAOTimelock'] }, - veBalDelegatorPCVDeposit: { - contractDependencies: ['core', 'balancerLensVeBalBal', 'balancerLensVeBalWeth'] - }, - balancerLensBpt30Fei70Weth: { - contractDependencies: ['oneConstantOracle', 'chainlinkEthUsdOracleWrapper'] - }, - balancerLensVeBalBal: { - contractDependencies: ['veBalDelegatorPCVDeposit', 'balUsdCompositeOracle', 'chainlinkEthUsdOracleWrapper'] - }, - balancerLensVeBalWeth: { - contractDependencies: ['veBalDelegatorPCVDeposit', 'balUsdCompositeOracle', 'chainlinkEthUsdOracleWrapper'] - }, roleBastion: { contractDependencies: ['core'] }, @@ -1070,6 +1061,18 @@ const dependencies: DependencyMap = { }, tribalCouncilSafe: { contractDependencies: ['tribalCouncilTimelock'] + }, + veBalDelegatorPCVDeposit: { + contractDependencies: ['core'] + }, + balancerLensVeBalWeth: { + contractDependencies: ['balUsdCompositeOracle', 'chainlinkEthUsdOracleWrapper'] + }, + balancerLensBpt30Fei70Weth: { + contractDependencies: ['oneConstantOracle', 'chainlinkEthUsdOracleWrapper'] + }, + pcvGuardian: { + contractDependencies: [] } }; diff --git a/protocol-configuration/mainnetAddresses.ts b/protocol-configuration/mainnetAddresses.ts index f4f6076cb..5c3f82269 100644 --- a/protocol-configuration/mainnetAddresses.ts +++ b/protocol-configuration/mainnetAddresses.ts @@ -34,6 +34,11 @@ const MainnetAddresses: MainnetAddresses = { pcvGuardian: { artifactName: 'PCVGuardian', address: '0x2D1b1b509B6432A73e3d798572f0648f6453a5D9', + category: AddressCategory.Deprecated + }, + pcvGuardianNew: { + artifactName: 'PCVGuardian', + address: '0x02435948F84d7465FB71dE45ABa6098Fc6eC2993', category: AddressCategory.Core }, pcvSentinel: { @@ -219,7 +224,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool18FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0x5A8CB4556e5D5935Af06beab8292905f48131479', - category: AddressCategory.PCV_V1 + category: AddressCategory.Deprecated }, rariPool22FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', @@ -244,7 +249,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool27FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0x91f50E3183a8CC30D2A981C3aFA85A2Bf6691c67', - category: AddressCategory.PCV_V1 + category: AddressCategory.Deprecated }, rariPool128FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', @@ -309,7 +314,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool90FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0x61d26126D2F8A44b41c1D8E1B1F276551DC8EEc6', - category: AddressCategory.PCV_V1 + category: AddressCategory.Deprecated }, rariPool91FeiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', @@ -391,9 +396,14 @@ const MainnetAddresses: MainnetAddresses = { address: '0xa8E388a1f19f2b33Be8bf2cCeC43641C10b4D1e5', category: AddressCategory.External // not really External, but not PCV }, - balancerLensBpt30Fei70Weth: { + balancerLensBpt30Fei70WethOld: { artifactName: 'BalancerPool2Lens', address: '0xb31F75550e97A2C4c7AC8d4355032B8AE8b9584D', + category: AddressCategory.Deprecated + }, + balancerLensBpt30Fei70Weth: { + artifactName: 'BalancerPool2Lens', + address: '0x673f7DFA863b611dE657759aEDE629b260F4E682', category: AddressCategory.PCV }, balancerLensVeBalBal: { @@ -494,22 +504,22 @@ const MainnetAddresses: MainnetAddresses = { rariPool146EthPCVDeposit: { artifactName: 'EthCompoundPCVDeposit', address: '0xC68412B72e68c30D4E6c0854b439CBBe957146e4', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool8DaiPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0x9CC46aB5A714f7cd24C59f33C5769039B5872491', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool8LusdPCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0xF846eE6E8EE9A6fbf51c7c65105CAbc041c048ad', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool18FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0x07F2DD7E6A78D96c08D0a8212f4097dCC129d629', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool19DpiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', @@ -539,7 +549,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool27FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0xe2e35097638F0Ff2EeCA2EF70F352Be37431945f', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool6FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', @@ -554,7 +564,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool8FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0xD6598a23418c7FEf7c0Dc863265515B623B720F9', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool9FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', @@ -574,7 +584,7 @@ const MainnetAddresses: MainnetAddresses = { rariPool90FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0xec54148CbC47bFF8FCc5e04e5E8083aDb8aF9aD9', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, rariPool91FeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', @@ -1969,13 +1979,18 @@ const MainnetAddresses: MainnetAddresses = { convexPoolPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0x1370CA8655C255948d6c6110066d78680601B7c2', - category: AddressCategory.PCV + category: AddressCategory.Deprecated }, - compoundPCVDepositWrapper: { + compoundFeiPCVDepositWrapper: { artifactName: 'PCVDepositWrapper', address: '0xB80B3dc4F8B30589477b2bA0e4EF2b8224bDf0a5', category: AddressCategory.PCV }, + compoundFeiPCVDeposit: { + artifactName: 'PCVDeposit', + address: '0xe1f2a7342459b54fbfea9f40695cdd46efadeeee', + category: AddressCategory.PCV_V1 + }, turboFusePCVDeposit: { artifactName: 'ERC20CompoundPCVDeposit', address: '0x2c47Fef515d2C70F2427706999E158533F7cF090', diff --git a/protocol-configuration/permissions.ts b/protocol-configuration/permissions.ts index 583a0d247..ca1aaae8c 100644 --- a/protocol-configuration/permissions.ts +++ b/protocol-configuration/permissions.ts @@ -17,26 +17,38 @@ export const permissions = { 'feiDAOTimelock', 'ratioPCVControllerV2', 'aaveEthPCVDripController', - 'pcvGuardian', + 'pcvGuardianNew', 'daiPCVDripController', 'lusdPCVDripController', 'ethPSMFeiSkimmer', 'lusdPSMFeiSkimmer', 'raiPCVDripController' ], - GUARDIAN_ROLE: ['multisig', 'pcvGuardian', 'pcvSentinel'], - ORACLE_ADMIN_ROLE: ['collateralizationOracleGuardian', 'optimisticTimelock', 'opsOptimisticTimelock'], + GUARDIAN_ROLE: ['multisig', 'pcvGuardianNew', 'pcvSentinel'], + ORACLE_ADMIN_ROLE: [ + 'collateralizationOracleGuardian', + 'optimisticTimelock', + 'opsOptimisticTimelock', + 'tribalCouncilTimelock' + ], SWAP_ADMIN_ROLE: ['pcvEquityMinter', 'optimisticTimelock'], BALANCER_MANAGER_ADMIN_ROLE: [], - PSM_ADMIN_ROLE: [], + RATE_LIMITED_MINTER_ADMIN: [], + PARAMETER_ADMIN: [], + PSM_ADMIN_ROLE: ['tribalCouncilTimelock'], TRIBAL_CHIEF_ADMIN_ROLE: ['optimisticTimelock', 'tribalChiefSyncV2'], + FUSE_ADMIN: ['optimisticTimelock', 'tribalChiefSyncV2', 'tribalCouncilTimelock'], VOTIUM_ADMIN_ROLE: ['opsOptimisticTimelock'], - PCV_GUARDIAN_ADMIN_ROLE: ['optimisticTimelock'], - METAGOVERNANCE_VOTE_ADMIN: ['feiDAOTimelock', 'opsOptimisticTimelock'], + PCV_GUARDIAN_ADMIN_ROLE: ['optimisticTimelock', 'tribalCouncilTimelock'], + PCV_SAFE_MOVER_ROLE: ['tribalCouncilTimelock'], + METAGOVERNANCE_VOTE_ADMIN: ['feiDAOTimelock', 'opsOptimisticTimelock', 'tribalCouncilTimelock'], METAGOVERNANCE_TOKEN_STAKING: ['feiDAOTimelock', 'opsOptimisticTimelock'], METAGOVERNANCE_GAUGE_ADMIN: ['feiDAOTimelock', 'optimisticTimelock'], ROLE_ADMIN: ['feiDAOTimelock', 'tribalCouncilTimelock'], POD_METADATA_REGISTER_ROLE: ['tribalCouncilSafe'], + FEI_MINT_ADMIN: ['feiDAOTimelock', 'tribalCouncilTimelock'], POD_VETO_ADMIN: ['nopeDAO'], - POD_ADMIN: ['tribalCouncilTimelock', 'podFactory'] + POD_ADMIN: ['tribalCouncilTimelock', 'podFactory'], + PCV_MINOR_PARAM_ROLE: ['feiDAOTimelock', 'optimisticTimelock', 'tribalCouncilTimelock'], + TOKEMAK_DEPOSIT_ADMIN_ROLE: ['optimisticTimelock', 'feiDAOTimelock', 'tribalCouncilTimelock'] }; diff --git a/scripts/utils/constructProposal.ts b/scripts/utils/constructProposal.ts index b7dc8c116..26bc1b218 100644 --- a/scripts/utils/constructProposal.ts +++ b/scripts/utils/constructProposal.ts @@ -1,7 +1,62 @@ -import { proposals } from 'hardhat'; +import hre, { proposals } from 'hardhat'; import { MainnetContracts, NamedAddresses, ProposalDescription } from '@custom-types/types'; import format from 'string-template'; -import { AlphaProposal } from '@idle-finance/hardhat-proposals-plugin/dist/src/proposals/compound-alpha'; +import { + AlphaProposal, + AlphaProposalBuilder +} from '@idle-finance/hardhat-proposals-plugin/dist/src/proposals/compound-alpha'; +import { BigNumber, utils } from 'ethers'; +import { InternalProposalState } from '@idle-finance/hardhat-proposals-plugin/dist/src/proposals/proposal'; +import { HardhatPluginError } from 'hardhat/plugins'; +import { PACKAGE_NAME, errors } from '@idle-finance/hardhat-proposals-plugin/dist/src/constants'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { time } from '@test/helpers'; + +export class SigmaProposal extends AlphaProposal { + protected async mineBlocks(blocks: any) { + const blocksToMine = BigNumber.from(blocks); + await hre.network.provider.send('hardhat_mine', [utils.hexStripZeros(blocksToMine.toHexString())]); + console.log( + `Mined ${blocksToMine.toString()} blocks via SigmaProposalBuilder. (kryptoklob just saved you ${ + blocksToMine.toNumber() / 10 + } seconds of your life.)` + ); + } + + protected async mineBlock(timestamp?: number) { + if (timestamp) { + await time.increaseTo(timestamp); + } else { + await hre.network.provider.send('evm_mine'); + } + } + + async simulate(fullSimulation = false, force?: boolean) { + if (this.internalState != InternalProposalState.UNSUBMITTED && !force) { + throw new HardhatPluginError(PACKAGE_NAME, errors.ALREADY_SIMULATED); + } + + if (fullSimulation) await this._fullSimulate(); + else await this._simulate(); + + this.internalState = InternalProposalState.SIMULATED; + } +} + +export class SigmaProposalBuilder extends AlphaProposalBuilder { + proposal: SigmaProposal; + + constructor(hre: HardhatRuntimeEnvironment, governor?: any, votingToken?: any, maxActions = 50) { + super(hre); + + this.maxActions = maxActions; + this.proposal = new SigmaProposal(hre, governor, votingToken); + } + + build() { + return this.proposal; + } +} /** * Constucts a hardhat proposal object @@ -13,13 +68,17 @@ export default async function constructProposal( contracts: MainnetContracts, contractAddresses: NamedAddresses, logging = false -): Promise { +): Promise { logging && console.log(`Constructing proposal...`); const proposalDescription = proposalInfo.description; - const proposalBuilder = proposals.builders.alpha(); - proposalBuilder.maxActions = 40; + const proposalBuilder = new SigmaProposalBuilder( + hre, + hre.config.proposals.governor, + hre.config.proposals.votingToken + ); + proposalBuilder.maxActions = 50; for (let i = 0; i < proposalInfo.commands.length; i += 1) { const command = proposalInfo.commands[i]; @@ -32,7 +91,6 @@ export default async function constructProposal( } proposalBuilder.setDescription(`${proposalInfo.title}\n${proposalDescription.toString()}`); // Set proposal description - const proposal = proposalBuilder.build(); logging && console.log(await proposal.printProposalInfo()); return proposal; diff --git a/sol-checksum.sh b/sol-checksum.sh new file mode 100755 index 000000000..e7fafe69b --- /dev/null +++ b/sol-checksum.sh @@ -0,0 +1,23 @@ +#!/bin/bash +RESULT_FILE=$1 + +if [ -f $RESULT_FILE ]; then + rm $RESULT_FILE +fi +touch $RESULT_FILE + +checksum_file() { + echo `openssl md5 $1 | awk '{print $2}'` +} + +FILES=() +while read -r -d ''; do + FILES+=("$REPLY") +done < <(find ./contracts -name '*.sol' -type f -print0) + +# Loop through files and append MD5 to result file +for FILE in ${FILES[@]}; do + echo `checksum_file $FILE` >> $RESULT_FILE +done +# Now sort the file so that it is +sort $RESULT_FILE -o $RESULT_FILE \ No newline at end of file diff --git a/test/helpers.ts b/test/helpers.ts index c691ce21b..40f7abccc 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -6,6 +6,7 @@ import { BigNumber, BigNumberish, Contract, Signer } from 'ethers'; import { NamedAddresses } from '@custom-types/types'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import EthersAdapter from '@gnosis.pm/safe-ethers-lib'; +import { BN } from 'ethereumjs-util'; import Safe from '@gnosis.pm/safe-core-sdk'; // use default BigNumber @@ -84,7 +85,8 @@ async function resetFork(): Promise { { forking: hre.config.networks.hardhat.forking ? { - jsonRpcUrl: hre.config.networks.hardhat.forking.url + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: hre.config.networks.hardhat.forking.blockNumber } : undefined } @@ -107,7 +109,7 @@ async function latestTime(): Promise { async function mine(): Promise { await hre.network.provider.request({ - method: 'evm_mine' + method: 'hardhat_mine' }); } @@ -133,6 +135,11 @@ async function getCore(): Promise { return core; } +const validateArraysEqual = (arrayA: string[], arrayB: string[]) => { + expect(arrayA.length).to.equal(arrayB.length); + arrayA.every((a) => expect(arrayB.map((b) => b.toLowerCase()).includes(a.toLowerCase()))); +}; + async function expectApprox( actual: string | number | BigNumberish, expected: string | number | BigNumberish, @@ -215,9 +222,11 @@ const time = { if (durationBN.lt(ethers.constants.Zero)) throw Error(`Cannot increase time by a negative amount (${duration})`); - await hre.network.provider.send('evm_increaseTime', [durationBN.toNumber()]); - - await hre.network.provider.send('evm_mine'); + if (durationBN.eq(ethers.constants.Zero)) { + await hre.network.provider.send('hardhat_mine'); + } else { + await hre.network.provider.send('hardhat_mine', ['0x2', ethers.utils.hexStripZeros(durationBN.toHexString())]); + } }, increaseTo: async (target: number | string | BigNumberish): Promise => { @@ -234,21 +243,15 @@ const time = { target = ethers.BigNumber.from(target); const currentBlock = await time.latestBlock(); - const start = Date.now(); - let notified; if (target.lt(currentBlock)) throw Error(`Target block #(${target}) is lower than current block #(${currentBlock})`); - while (ethers.BigNumber.from(await time.latestBlock()).lt(target)) { - if (!notified && Date.now() - start >= 5000) { - notified = true; - console.warn(`You're advancing many blocks; this test may be slow.`); - } - await time.advanceBlock(); - } + + const diff = target.sub(currentBlock); + await hre.network.provider.send('hardhat_mine', [ethers.utils.hexStripZeros(diff.toHexString())]); }, advanceBlock: async (): Promise => { - await hre.network.provider.send('evm_mine'); + await hre.network.provider.send('hardhat_mine'); } }; @@ -342,5 +345,6 @@ export { resetFork, overwriteChainlinkAggregator, performDAOAction, - initialiseGnosisSDK + initialiseGnosisSDK, + validateArraysEqual }; diff --git a/test/integration/setup/index.ts b/test/integration/setup/index.ts index bf50250dd..ee1e8bb31 100644 --- a/test/integration/setup/index.ts +++ b/test/integration/setup/index.ts @@ -1,3 +1,4 @@ +import { ethers } from 'hardhat'; import { permissions } from '@protocol/permissions'; import { getAllContractAddresses, getAllContracts } from './loadContracts'; import { @@ -21,6 +22,8 @@ import constructProposal from '@scripts/utils/constructProposal'; import '@nomiclabs/hardhat-ethers'; import { resetFork } from '@test/helpers'; import simulateOAProposal from '@scripts/utils/simulateOAProposal'; +import { forceEth } from '@test/integration/setup/utils'; +import { getImpersonatedSigner } from '@test/helpers'; /** * Coordinate initialising an end-to-end testing environment @@ -156,6 +159,53 @@ export class TestEndtoEndCoordinator implements TestCoordinator { await proposal.simulate(); } + if (config.category === ProposalCategory.DEBUG) { + console.log('Simulating DAO proposal in DEBUG mode (step by step)...'); + console.log(' Title: ', config.proposal.title); + + const signer = await getImpersonatedSigner(contracts.feiDAOTimelock.address); + await forceEth(contracts.feiDAOTimelock.address); + + let totalGasUsed = 0; + for (let i = 0; i < config.proposal.commands.length; i++) { + const cmd = config.proposal.commands[i]; + // build tx & print details + console.log(' Step' + (config.proposal.commands.length >= 10 && i < 10 ? ' ' : ''), i, ':', cmd.description); + let types = []; + if (cmd.method.indexOf('(') !== -1 && cmd.method.indexOf('()') === -1) { + // e.g. ['address', 'bytes32', 'uint256'], or empty array [] + types = cmd.method.split('(')[1].split(')')[0].split(','); + } + const cmdArguments = cmd.arguments.map((arg) => { + if (arg.indexOf('{') == 0) { + arg = contractAddresses[arg.replace('{', '').replace('}', '')] || arg; + } + return arg; + }); + const functionSig = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(cmd.method)); + const calldata = ethers.utils.defaultAbiCoder + .encode(types, cmdArguments) + .replace('0x', functionSig.substring(0, 10)); // prepend function signature + const to = contractAddresses[cmd.target] || cmd.target; + const value = cmd.values; + console.log(' Target:', cmd.target, '[' + to + ']'); + console.log(' Method:', cmd.method); + types.forEach((type, i) => { + console.log(' Argument', i, '[' + type + ']', cmdArguments[i]); + }); + //console.log(' Value:', value); + //console.log(' Calldata:', calldata); + console.log(' Calling... '); + + // send tx + const tx = await signer.sendTransaction({ data: calldata, to, value: Number(value) }); + const d = await tx.wait(); + console.log(' Done. Used ' + d.cumulativeGasUsed.toString() + ' gas.'); + totalGasUsed += Number(d.cumulativeGasUsed.toString()); + } + console.log(' Done. Used', totalGasUsed, 'gas in total.'); + } + if (config.category === ProposalCategory.OA) { this.config.logging && console.log(`Simulating OA proposal...`); await simulateOAProposal( diff --git a/test/integration/setup/loadContracts.ts b/test/integration/setup/loadContracts.ts index a3faf88ec..c2dae32dc 100644 --- a/test/integration/setup/loadContracts.ts +++ b/test/integration/setup/loadContracts.ts @@ -12,19 +12,16 @@ interface MainnetContractsJSON { } export async function getAllContracts(): Promise { - const contracts: MainnetContracts = {} as MainnetContracts; const addresses = mainnetAddresses as MainnetContractsJSON; - - for (const mainnetAddressEntryName in addresses) { - const mainnetAddressEntry = addresses[mainnetAddressEntryName]; - const artifactName = mainnetAddressEntry.artifactName; - const address = mainnetAddressEntry.address; - if (artifactName == 'unknown') continue; - const contract = await ethers.getContractAt(artifactName, address); - contracts[mainnetAddressEntryName] = contract; - } - - return contracts; + const contractsAsArrayEntries = await Promise.all( + Object.entries(addresses) + .filter((entry) => entry[1].artifactName != 'unknown') + .map(async (entry) => { + return [entry[0], await ethers.getContractAt(entry[1].artifactName, entry[1].address)]; + }) + ); + + return Object.fromEntries(contractsAsArrayEntries) as MainnetContracts; } export function getAllContractAddresses(): NamedAddresses { diff --git a/test/integration/tests/backstop.ts b/test/integration/tests/backstop.ts index 9eade3b5a..9988b00cd 100644 --- a/test/integration/tests/backstop.ts +++ b/test/integration/tests/backstop.ts @@ -21,7 +21,6 @@ describe('e2e-backstop', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/balancer-weightedpool.ts b/test/integration/tests/balancer-weightedpool.ts index a63600648..8c10e6fd7 100644 --- a/test/integration/tests/balancer-weightedpool.ts +++ b/test/integration/tests/balancer-weightedpool.ts @@ -21,7 +21,6 @@ describe('balancer-weightedpool', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/buybacks.ts b/test/integration/tests/buybacks.ts index a81ef839b..974ffac88 100644 --- a/test/integration/tests/buybacks.ts +++ b/test/integration/tests/buybacks.ts @@ -26,7 +26,6 @@ describe('e2e-buybacks', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/daiFixedPricePSM.ts b/test/integration/tests/daiFixedPricePSM.ts index 5670c8e59..551b0fcf3 100644 --- a/test/integration/tests/daiFixedPricePSM.ts +++ b/test/integration/tests/daiFixedPricePSM.ts @@ -14,7 +14,6 @@ import { FixedPricePSM } from '@custom-types/contracts'; before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); describe('e2e-peg-stability-module', function () { @@ -123,6 +122,16 @@ describe('e2e-peg-stability-module', function () { beforeEach(async () => { await fei.connect(impersonatedSigners[minterAddress]).mint(userAddress, redeemAmount); await fei.connect(impersonatedSigners[userAddress]).approve(daiPSM.address, redeemAmount); + + const isPaused = await daiPSM.paused(); + if (isPaused) { + await daiPSM.unpause(); + } + + const isRedeemPaused = await daiPSM.redeemPaused(); + if (isRedeemPaused) { + await daiPSM.unpauseRedeem(); + } }); it('exchanges 10,000,000 FEI for DAI', async () => { diff --git a/test/integration/tests/dao.ts b/test/integration/tests/dao.ts index 7e4ad7515..2257af38f 100644 --- a/test/integration/tests/dao.ts +++ b/test/integration/tests/dao.ts @@ -20,7 +20,6 @@ describe('e2e-dao', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { @@ -97,7 +96,7 @@ describe('e2e-dao', function () { // advance to end of voting period const endBlock = (await feiDAO.proposals(pid)).endBlock; - await time.advanceBlockTo(endBlock.toString()); + await time.advanceBlockTo(endBlock.toNumber()); // queue await feiDAO['queue(address[],uint256[],bytes[],bytes32)']( diff --git a/test/integration/tests/ethPSM.ts b/test/integration/tests/ethPSM.ts index 01d35912e..a2713519f 100644 --- a/test/integration/tests/ethPSM.ts +++ b/test/integration/tests/ethPSM.ts @@ -40,7 +40,6 @@ describe('eth PSM', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/fei.ts b/test/integration/tests/fei.ts index e0abe1991..5a8687511 100644 --- a/test/integration/tests/fei.ts +++ b/test/integration/tests/fei.ts @@ -22,7 +22,6 @@ describe('e2e-fei', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/fip-38-tokemak.ts b/test/integration/tests/fip-38-tokemak.ts index 7d78c1764..1f24bd066 100644 --- a/test/integration/tests/fip-38-tokemak.ts +++ b/test/integration/tests/fip-38-tokemak.ts @@ -23,7 +23,6 @@ describe('e2e-fip-38-tokemak', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/fuse.ts b/test/integration/tests/fuse.ts index 835907156..99a298480 100644 --- a/test/integration/tests/fuse.ts +++ b/test/integration/tests/fuse.ts @@ -11,7 +11,6 @@ import { forceEth } from '../setup/utils'; before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); describe('e2e-fuse', function () { diff --git a/test/integration/tests/lusdPSM.ts b/test/integration/tests/lusdPSM.ts index 088a53539..bf7ed53ba 100644 --- a/test/integration/tests/lusdPSM.ts +++ b/test/integration/tests/lusdPSM.ts @@ -38,7 +38,6 @@ describe('lusd PSM', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/merger.ts b/test/integration/tests/merger.ts.disabled similarity index 99% rename from test/integration/tests/merger.ts rename to test/integration/tests/merger.ts.disabled index 636682869..561000e02 100644 --- a/test/integration/tests/merger.ts +++ b/test/integration/tests/merger.ts.disabled @@ -22,7 +22,6 @@ describe('e2e-merger', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/old/migrateProxies/index.ts b/test/integration/tests/old/migrateProxies/index.ts index c829a3079..70d6cf2d3 100644 --- a/test/integration/tests/old/migrateProxies/index.ts +++ b/test/integration/tests/old/migrateProxies/index.ts @@ -32,7 +32,6 @@ describe.skip('e2e-migrate-proxies', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/pcv.ts b/test/integration/tests/pcv.ts index 0889d92ed..0e0ff263a 100644 --- a/test/integration/tests/pcv.ts +++ b/test/integration/tests/pcv.ts @@ -74,7 +74,7 @@ describe('e2e-pcv', function () { describe('PCV Guardian', async () => { it('can withdraw PCV and pause', async () => { - const pcvGuardian = contracts.pcvGuardian; + const pcvGuardian = contracts.pcvGuardianNew; const amount = await contracts.compoundEthPCVDeposit.balance(); await pcvGuardian.withdrawToSafeAddress( @@ -89,7 +89,7 @@ describe('e2e-pcv', function () { }); it('can withdraw PCV and pause', async () => { - const pcvGuardian = contracts.pcvGuardian; + const pcvGuardian = contracts.pcvGuardianNew; const feiBalanceBefore = await contracts.fei.balanceOf(contractAddresses.feiDAOTimelock); await pcvGuardian.withdrawToSafeAddress( diff --git a/test/integration/tests/podOperation.ts b/test/integration/tests/podOperation.ts index 9ab8d2594..2343038c5 100644 --- a/test/integration/tests/podOperation.ts +++ b/test/integration/tests/podOperation.ts @@ -33,6 +33,8 @@ describe('Pod operation and veto', function () { let timelockAddress: string; let podTimelock: Contract; let registryTxData: string; + let registryTxData2: string; + let safeSDK: any; const proposalId = '1234'; const proposalMetadata = 'FIP_XX: This tests that the governance upgrade flow works'; @@ -40,10 +42,9 @@ describe('Pod operation and veto', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); - beforeEach(async function () { + before(async function () { // Setup test environment and get contracts const version = 1; // Set deploy address to Tom's address. This has Orca SHIP @@ -109,7 +110,7 @@ describe('Pod operation and veto', function () { // 2.0 Instantiate Gnosis SDK podTimelock = new ethers.Contract(timelockAddress, timelockABI, podMemberSigner); - const safeSDK = await initialiseGnosisSDK(podMemberSigner, safeAddress); + safeSDK = await initialiseGnosisSDK(podMemberSigner, safeAddress); // 3. TribalCouncil authorises pod with POD_METADATA_REGISTER_ROLE role await contracts.core @@ -137,6 +138,7 @@ describe('Pod operation and veto', function () { '0x0000000000000000000000000000000000000000000000000000000000000001', podConfig.minDelay ]); + const safeTransaction = await safeSDK.createTransaction(txArgs); // 3.0 Execute transaction on Safe @@ -170,6 +172,24 @@ describe('Pod operation and veto', function () { }); it('should allow the nopeDAO to veto a proposal through the pod', async () => { + const proposalId2 = '4321'; + const registryTxData2 = contracts.governanceMetadataRegistry.interface.encodeFunctionData('registerProposal', [ + podId, + proposalId2, + proposalMetadata + ]); + const txArgs2 = createSafeTxArgs(podTimelock, 'schedule', [ + contractAddresses.governanceMetadataRegistry, + 0, + registryTxData2, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000001', + podConfig.minDelay + ]); + const safeTransaction2 = await safeSDK.createTransaction(txArgs2); + const executeTxResponse2 = await safeSDK.executeTransaction(safeTransaction2); + await executeTxResponse2.transactionResponse?.wait(); + // 1. Create proposal on the NopeDAO to veto. This proposal needs to // call the podAdminGateway.veto() method with the proposalId that is in the timelock // 2. Have a member with >quorum TRIBE vote for proposal @@ -178,7 +198,7 @@ describe('Pod operation and veto', function () { const timelockProposalId = await podTimelock.hashOperation( contractAddresses.governanceMetadataRegistry, 0, - registryTxData, + registryTxData2, '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000001' ); diff --git a/test/integration/tests/psm.ts b/test/integration/tests/psm.ts index 9cc59330b..944202fc2 100644 --- a/test/integration/tests/psm.ts +++ b/test/integration/tests/psm.ts @@ -9,7 +9,7 @@ import proposals from '@test/integration/proposals_config'; import { forceEth } from '@test/integration/setup/utils'; import { Contract, Signer } from 'ethers'; import { expectApprox } from '@test/helpers'; -import { FeiDAO, WETH9 } from '@custom-types/contracts'; +import { WETH9 } from '@custom-types/contracts'; const toBN = ethers.BigNumber.from; @@ -23,10 +23,8 @@ describe('e2e-peg-stability-module', function () { let ethPSMRouter: Contract; let userAddress; let minterAddress; - let governorAddress; let weth: Contract; let dai: Contract; - let daiPSM: Contract; let raiPriceBoundPSM: Contract; let ethPSM: Contract; let fei: Contract; @@ -40,7 +38,6 @@ describe('e2e-peg-stability-module', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { @@ -77,7 +74,6 @@ describe('e2e-peg-stability-module', function () { } = contracts); doLogging && console.log(`Environment loaded.`); weth = contracts.weth as WETH9; - daiPSM = daiFixedPricePSM; // add any addresses you want to impersonate here const impersonatedAddresses = [ @@ -289,7 +285,7 @@ describe('e2e-peg-stability-module', function () { ); await contracts.compoundDaiPCVDeposit.deposit(); await contracts.dai.connect(signer).transfer( - daiPSM.address, + daiFixedPricePSM.address, '5500000000000000000000000' // 5.5M ); }); @@ -306,16 +302,20 @@ describe('e2e-peg-stability-module', function () { it('does drip when the dai PSM is under the threshold', async () => { const timelock = await getImpersonatedSigner(feiDAOTimelock.address); - await daiPSM + await daiFixedPricePSM .connect(timelock) - .withdrawERC20(dai.address, contracts.compoundDaiPCVDeposit.address, await dai.balanceOf(daiPSM.address)); + .withdrawERC20( + dai.address, + contracts.compoundDaiPCVDeposit.address, + await dai.balanceOf(daiFixedPricePSM.address) + ); await contracts.compoundDaiPCVDeposit.deposit(); - expect(await dai.balanceOf(daiPSM.address)).to.be.equal(0); + expect(await dai.balanceOf(daiFixedPricePSM.address)).to.be.equal(0); await daiPCVDripController.drip(); - expect(await dai.balanceOf(daiPSM.address)).to.be.equal(await daiPCVDripController.dripAmount()); + expect(await dai.balanceOf(daiFixedPricePSM.address)).to.be.equal(await daiPCVDripController.dripAmount()); }); }); @@ -324,15 +324,27 @@ describe('e2e-peg-stability-module', function () { const redeemAmount = 500_000; beforeEach(async () => { await fei.connect(impersonatedSigners[minterAddress]).mint(userAddress, redeemAmount); - await fei.connect(impersonatedSigners[userAddress]).approve(daiPSM.address, redeemAmount); + await fei.connect(impersonatedSigners[userAddress]).approve(daiFixedPricePSM.address, redeemAmount); + + const isPaused = await daiFixedPricePSM.paused(); + if (isPaused) { + await daiFixedPricePSM.unpause(); + } + + const isRedeemPaused = await daiFixedPricePSM.redeemPaused(); + if (isRedeemPaused) { + await daiFixedPricePSM.unpauseRedeem(); + } }); it('exchanges 500,000 FEI for DAI', async () => { const startingFEIBalance = await fei.balanceOf(userAddress); const startingDAIBalance = await dai.balanceOf(userAddress); - const expectedDAIAmount = await daiPSM.getRedeemAmountOut(redeemAmount); + const expectedDAIAmount = await daiFixedPricePSM.getRedeemAmountOut(redeemAmount); - await daiPSM.connect(impersonatedSigners[userAddress]).redeem(userAddress, redeemAmount, expectedDAIAmount); + await daiFixedPricePSM + .connect(impersonatedSigners[userAddress]) + .redeem(userAddress, redeemAmount, expectedDAIAmount); const endingFEIBalance = await fei.balanceOf(userAddress); const endingDAIBalance = await dai.balanceOf(userAddress); @@ -343,7 +355,7 @@ describe('e2e-peg-stability-module', function () { }); it('DAI price sanity check', async () => { - const actualDAIAmountOut = await daiPSM.getRedeemAmountOut(redeemAmount); + const actualDAIAmountOut = await daiFixedPricePSM.getRedeemAmountOut(redeemAmount); await expectApprox(actualDAIAmountOut, redeemAmount); }); }); @@ -356,17 +368,19 @@ describe('e2e-peg-stability-module', function () { const daiSigner = await getImpersonatedSigner(daiAccount); await forceEth(daiAccount); await dai.connect(daiSigner).transfer(userAddress, mintAmount); - await dai.connect(impersonatedSigners[userAddress]).approve(daiPSM.address, mintAmount); + await dai.connect(impersonatedSigners[userAddress]).approve(daiFixedPricePSM.address, mintAmount); }); it('mint succeeds with 500_000 DAI', async () => { - const minAmountOut = await daiPSM.getMintAmountOut(mintAmount / 2); + const minAmountOut = await daiFixedPricePSM.getMintAmountOut(mintAmount / 2); const userStartingFEIBalance = await fei.balanceOf(userAddress); - const psmStartingDAIBalance = await dai.balanceOf(daiPSM.address); + const psmStartingDAIBalance = await dai.balanceOf(daiFixedPricePSM.address); - await daiPSM.connect(impersonatedSigners[userAddress]).mint(userAddress, mintAmount / 2, minAmountOut); + await daiFixedPricePSM + .connect(impersonatedSigners[userAddress]) + .mint(userAddress, mintAmount / 2, minAmountOut); - const psmEndingDAIBalance = await dai.balanceOf(daiPSM.address); + const psmEndingDAIBalance = await dai.balanceOf(daiFixedPricePSM.address); const userEndingFEIBalance = await fei.balanceOf(userAddress); expect(userEndingFEIBalance.sub(userStartingFEIBalance)).to.be.gte(minAmountOut); @@ -374,7 +388,7 @@ describe('e2e-peg-stability-module', function () { }); it('DAI price sanity check', async () => { - const actualDAIAmountOut = await daiPSM.getMintAmountOut(mintAmount); + const actualDAIAmountOut = await daiFixedPricePSM.getMintAmountOut(mintAmount); await expectApprox(actualDAIAmountOut, mintAmount); }); }); @@ -386,6 +400,12 @@ describe('e2e-peg-stability-module', function () { beforeEach(async () => { await fei.connect(impersonatedSigners[minterAddress]).mint(userAddress, redeemAmount); await fei.connect(impersonatedSigners[userAddress]).approve(raiPriceBoundPSM.address, redeemAmount); + + // Ensure RAI PSM has sufficient balance to redeem against + const raiWhale = '0x618788357d0ebd8a37e763adab3bc575d54c2c7d'; + await forceEth(raiWhale); + const raiWhaleSigner = await getImpersonatedSigner(raiWhale); + await rai.connect(raiWhaleSigner).transfer(raiPriceBoundPSM.address, redeemAmount); }); it('exchanges 1000 FEI for rai', async () => { diff --git a/test/integration/tests/staking.ts b/test/integration/tests/staking.ts index 171444794..72d9caa4f 100644 --- a/test/integration/tests/staking.ts +++ b/test/integration/tests/staking.ts @@ -15,6 +15,7 @@ import { expectApprox, getImpersonatedSigner, resetFork, time } from '@test/help import proposals from '@test/integration/proposals_config'; import { TestEndtoEndCoordinator } from '../setup'; import { forceEth } from '@test/integration/setup/utils'; +import { BN } from 'ethereumjs-util'; const toBN = ethers.BigNumber.from; @@ -28,7 +29,6 @@ describe('e2e-staking', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { @@ -215,9 +215,9 @@ describe('e2e-staking', function () { const startingTribeBalance = await tribe.balanceOf(rariRewardsDistributorDelegator); const blocksToAdvance = 10; - for (let i = 0; i < blocksToAdvance; i++) { - await time.advanceBlock(); - } + await hre.network.provider.send('hardhat_mine', [ + ethers.utils.hexStripZeros(BigNumber.from(blocksToAdvance).toHexString()) + ]); /// add 1 as calling the harvest is another block where rewards are received const pendingTribe = toBN(blocksToAdvance + 1) diff --git a/test/integration/tests/tribalCouncil.ts b/test/integration/tests/tribalCouncil.ts index a44ecd28a..f21126f64 100644 --- a/test/integration/tests/tribalCouncil.ts +++ b/test/integration/tests/tribalCouncil.ts @@ -33,7 +33,6 @@ describe('Tribal Council', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/integration/tests/turboPCVDeposit.ts b/test/integration/tests/turboPCVDeposit.ts index d4442a3ae..b2b8b429e 100644 --- a/test/integration/tests/turboPCVDeposit.ts +++ b/test/integration/tests/turboPCVDeposit.ts @@ -23,7 +23,6 @@ describe('Turbo PCV deposit', function () { before(async () => { chai.use(CBN(ethers.BigNumber)); chai.use(solidity); - await resetFork(); }); before(async function () { diff --git a/test/unit/dao/governor/FeiDao.test.ts b/test/unit/dao/governor/FeiDao.test.ts index c3b2c106f..6c383bfef 100644 --- a/test/unit/dao/governor/FeiDao.test.ts +++ b/test/unit/dao/governor/FeiDao.test.ts @@ -138,7 +138,7 @@ describe('FeiDAO', function () { // advance to end of voting period const endBlock = (await feiDAO.proposals(pid)).endBlock; - await time.advanceBlockTo(endBlock.toString()); + await time.advanceBlockTo(endBlock.toNumber()); // queue await feiDAO['queue(uint256)'](pid); diff --git a/test/unit/pcv/PCVGuardian.test.ts b/test/unit/pcv/PCVGuardian.test.ts index bff9fe4e5..7dd10e845 100644 --- a/test/unit/pcv/PCVGuardian.test.ts +++ b/test/unit/pcv/PCVGuardian.test.ts @@ -85,34 +85,32 @@ describe('PCV Guardian', function () { describe('access control', async () => { it('should revert when calling setSafeAddress & setSafeAddresses from a non-governor address', async () => { - await expect(pcvGuardianWithoutStartingAddresses.setSafeAddress(userAddress)).to.be.revertedWith( - 'CoreRef: Caller is not a governor' - ); + await expect(pcvGuardianWithoutStartingAddresses.setSafeAddress(userAddress)).to.be.revertedWith('UNAUTHORIZED'); await expect( pcvGuardianWithoutStartingAddresses.setSafeAddresses([userAddress, userAddress2]) - ).to.be.revertedWith('CoreRef: Caller is not a governor'); + ).to.be.revertedWith('UNAUTHORIZED'); }); it('should revert when calling unsetSafeAddress & unsetSafeAddresses from a non-guardian-or-governor-or-admin address', async () => { await expect(pcvGuardianWithoutStartingAddresses.unsetSafeAddress(userAddress)).to.be.revertedWith( - 'CoreRef: Caller is not governor or guardian or admin' + 'UNAUTHORIZED' ); await expect( pcvGuardianWithoutStartingAddresses.unsetSafeAddresses([userAddress, userAddress2]) - ).to.be.revertedWith('CoreRef: Caller is not governor or guardian or admin'); + ).to.be.revertedWith('UNAUTHORIZED'); }); it('should revert when calling withdrawToSafeAddress from a non-guardian-or-governor-or-admin address', async () => { await expect( pcvGuardianWithoutStartingAddresses.withdrawToSafeAddress(userAddress, userAddress, 1, false, false) - ).to.be.revertedWith('CoreRef: Caller is not governor or guardian or admin'); + ).to.be.revertedWith('UNAUTHORIZED'); }); it('should revert when calling withdrawETHToSafeAddress from a non-guardian-or-governor-or-admin address', async () => { await expect( pcvGuardianWithoutStartingAddresses.withdrawETHToSafeAddress(userAddress, userAddress, 1, false, false) - ).to.be.revertedWith('CoreRef: Caller is not governor or guardian or admin'); + ).to.be.revertedWith('UNAUTHORIZED'); }); it('should revert when calling withdrawERC20ToSafeAddress from a non-guardian-or-governor-or-admin address', async () => { @@ -125,7 +123,7 @@ describe('PCV Guardian', function () { false, false ) - ).to.be.revertedWith('CoreRef: Caller is not governor or guardian or admin'); + ).to.be.revertedWith('UNAUTHORIZED'); }); it('should allow the governor to add a safe address', async () => { @@ -209,6 +207,13 @@ describe('PCV Guardian', function () { expect(await token.balanceOf(userAddress)).to.eq(1); }); + it('should withdraw from a token-pcv deposit when called by the governor', async () => { + await pcvGuardianWithoutStartingAddresses + .connect(impersonatedSigners[governorAddress]) + .withdrawToSafeAddress(tokenPCVDeposit.address, userAddress, 1, false, false); + expect(await token.balanceOf(userAddress)).to.eq(1); + }); + it('should withdraw from a token-pcv deposit and deposit after', async () => { await pcvGuardianWithoutStartingAddresses .connect(impersonatedSigners[governorAddress]) diff --git a/test/unit/staking/TribalChiefPart1.test.ts b/test/unit/staking/TribalChiefPart1.test.ts index 6c756ab75..c49be5ecf 100644 --- a/test/unit/staking/TribalChiefPart1.test.ts +++ b/test/unit/staking/TribalChiefPart1.test.ts @@ -9,8 +9,9 @@ import { time } from '../../helpers'; import { expectRevert, expectUnspecifiedRevert, getCore, getAddresses, expectApprox } from '../../helpers'; import { expect } from 'chai'; import hre, { ethers } from 'hardhat'; -import { Signer } from 'ethers'; +import { BigNumber, Signer } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; +import { BN } from 'ethereumjs-util'; const toBN = ethers.BigNumber.from; @@ -482,10 +483,7 @@ describe('TribalChief', () => { pid ); - for (let i = 0; i < 98; i++) { - await time.advanceBlock(); - } - + await hre.network.provider.send('hardhat_mine', [ethers.utils.hexStripZeros(BigNumber.from(98).toHexString())]); await this.tribalChief.updatePool(pid); const expectedAccTribePerShare = toBN(100) diff --git a/test/unit/staking/TribalChiefPart2.test.ts b/test/unit/staking/TribalChiefPart2.test.ts index 17a1a279d..79f9f4aaf 100644 --- a/test/unit/staking/TribalChiefPart2.test.ts +++ b/test/unit/staking/TribalChiefPart2.test.ts @@ -9,8 +9,9 @@ import { time } from '../../helpers'; import { expectRevert, expectUnspecifiedRevert, getCore, getAddresses, expectApprox } from '../../helpers'; import { expect } from 'chai'; import hre, { ethers } from 'hardhat'; -import { Signer } from 'ethers'; +import { BigNumber, Signer } from 'ethers'; import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'; +import { BN } from 'ethereumjs-util'; const toBN = ethers.BigNumber.from; @@ -600,9 +601,7 @@ describe('TribalChief', () => { // to the staked amount which is total staked x 2 expect((await this.tribalChief.poolInfo(pid)).virtualTotalSupply).to.be.equal(toBN(totalStaked).mul(toBN('2'))); - for (let i = 0; i < 50; i++) { - await time.advanceBlock(); - } + await hre.network.provider.send('hardhat_mine', [ethers.utils.hexStripZeros(BigNumber.from(50).toHexString())]); let pendingTribe = await this.tribalChief.pendingRewards(pid, userAddress); await this.tribalChief @@ -623,9 +622,7 @@ describe('TribalChief', () => { expect(await this.LPToken.balanceOf(userAddress)).to.be.equal(toBN(totalStaked)); expect(await this.tribe.balanceOf(userAddress)).to.be.gte(pendingTribe); - for (let i = 0; i < 50; i++) { - await time.advanceBlock(); - } + await hre.network.provider.send('hardhat_mine', [ethers.utils.hexStripZeros(BigNumber.from(50).toHexString())]); pendingTribe = await this.tribalChief.pendingRewards(pid, userAddress); const currentTribe = await this.tribe.balanceOf(userAddress); // assert that the virtual total supply is equal to the staked amount diff --git a/types/types.ts b/types/types.ts index 3e5129014..f0021d668 100644 --- a/types/types.ts +++ b/types/types.ts @@ -62,6 +62,7 @@ export type DependencyMap = { [key: string]: Dependency }; export enum ProposalCategory { DAO, + DEBUG, OA, None }