From a00ec6351843a3fe77650ac77654bed832d2583d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Tue, 7 Nov 2023 15:53:43 +0100 Subject: [PATCH] Adapting the tests (WIP) --- README.md | 94 +++++- package.json | 6 +- .../deploy/01_repo/10_create_repo.ts | 8 +- .../contracts/deploy/02_setup/10_setup.ts | 25 +- .../deploy/02_setup/11_setup_conclude.ts | 64 +--- .../contracts/deploy/02_setup/12_publish.ts | 9 +- packages/contracts/plugin-setup-params.ts | 32 +- .../contracts/src/GovernancePluginsSetup.sol | 32 +- .../test/integration-testing/deployment.ts | 22 +- ...g-setup.ts => governance-plugins-setup.ts} | 26 +- .../member-access-setup.ts | 154 --------- ...n-setup.ts => governance-plugins-setup.ts} | 251 +++++++++++---- .../member-access-plugin-setup.ts | 302 ------------------ 13 files changed, 359 insertions(+), 666 deletions(-) rename packages/contracts/test/integration-testing/{main-voting-setup.ts => governance-plugins-setup.ts} (84%) delete mode 100644 packages/contracts/test/integration-testing/member-access-setup.ts rename packages/contracts/test/unit-testing/{main-voting-plugin-setup.ts => governance-plugins-setup.ts} (50%) delete mode 100644 packages/contracts/test/unit-testing/member-access-plugin-setup.ts diff --git a/README.md b/README.md index c618008..a4f1769 100644 --- a/README.md +++ b/README.md @@ -422,9 +422,11 @@ This is taken care by the `DAOFactory`. The DAO creator calls `daoFactory.create - The call contains: - The DAO settings - An array with the details and the settings of the desired plugins -- The method will deploy a new DAO and set itself as ROOT -- It will then call `prepareInstallation()` on all plugins and `applyInstallation()` right away -- It will finally drop `ROOT_PERMISSION` on itself +- The method will deploy a new DAO and grant `ROOT_PERMISSION` to the `DaoFactory`, temporarily + - Given the settings of the desired plugins, it will call the `PluginSetupProcessor` +- The PSP will then call `prepareInstallation()` on the given plugin set up contract +- Immedially after, `applyInstallation()` will be called by the `DaoFactory` +- The DaoFactory drops `ROOT_PERMISSION` on itself [See a JS example of installing plugins during a DAO's deployment](https://devs.aragon.org/docs/sdk/examples/client/create-dao#create-a-dao) @@ -432,9 +434,9 @@ This is taken care by the `DAOFactory`. The DAO creator calls `daoFactory.create Plugin changes need a proposal to be passed when the DAO already exists. -1. Calling `pluginSetup.prepareInstallation()` +1. Calling `pluginSetupProcessor.prepareInstallation()` which will call `prepareInstallation()` on the plugin's setup contract - A new plugin instance is deployed with the desired settings - - The call requests a set of permissions to be applied by the DAO + - The call returns a set of requested permissions to be applied by the DAO 2. Editors pass a proposal to make the DAO call `applyInstallation()` on the [PluginSetupProcessor](https://devs.aragon.org/docs/osx/how-it-works/framework/plugin-management/plugin-setup/) - This applies the requested permissions and the plugin becomes installed @@ -442,6 +444,88 @@ See `SpacePluginSetup`, `PersonalSpaceAdminPluginSetup`, `MemberAccessPluginSetu [Learn more about plugin setup's](https://devs.aragon.org/docs/osx/how-it-works/framework/plugin-management/plugin-setup/) and [preparing installations](https://devs.aragon.org/docs/sdk/examples/client/prepare-installation). +### Passing install parameters + +In both of the cases described above, a call to `prepareInstallation()` will be made by the `PluginSetupProcessor` from OSx. + +```solidity +function prepareInstallation( + address _dao, + bytes memory _data +) external returns (address plugin, PreparedSetupData memory preparedSetupData) +``` + +- The first parameter (dao address) will be provided by the PSP. +- The second parameter allows to pass an arbitrary array of bytes, encoding any set of custom settings that the plugin needs to receive. + +The first step for `prepareInstallation()` is to decode them and use them on the deployment script as needed: + +```solidity +// Decode incoming params +( + string memory _firstBlockContentUri, + address _predecessorAddress, + address _pluginUpgrader +) = abi.decode(_data, (string, address, address)); +``` + +The JSON encoded ABI definition can be found at the corresponding `-build-metadata.json` file: + +```json +{ + // ... + "pluginSetup": { + "prepareInstallation": { + // ... + "inputs": [ + { + "name": "firstBlockContentUri", + "type": "string", + "internalType": "string", + "description": "The inital contents of the first block item." + }, + { + "internalType": "address", + "name": "predecessorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "pluginUpgrader", + "type": "address" + } + ] + }, +``` + +The same also applies to `prepareUpdate` (if present) and to `prepareUninstallation`. + +### Available setup contracts + +#### GovernancePluginsSetup + +This contracts implements the deployment script for: + +- `MainVotingPlugin` +- `MemberAccessPlugin` + +The second plugin needs to know the address of the first one, therefore the contract deploys them together. + +##### Note + +When preparing the installation, an `InstallationPrepared` event is emitted. Using Typechain with Ethers: + +- `event.args.preparedSetupData.plugin` contains the address of the Main Voting plugin +- `event.args.preparedSetupData.helpers` contains an array with the address of the Member Access plugin + +#### SpacePluginSetup + +This contract implements the deployment script for the `SpacePlugin` contract. + +#### PersonalSpaceAdminPluginSetup + +This contract implements the deployment script for the `PersonalSpaceAdminPlugin` contract. + ## Deploying a DAO The recommended way to create a DAO is by using `@aragon/sdk-client`. It uses the `DAOFactory` under the hood and it reduces the amount of low level interactions with the protocol. diff --git a/package.json b/package.json index d2b3960..c4be9d7 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,9 @@ "typescript": "5.0.4" }, "scripts": { - "build": "cd ./packages/contracts && yarn build && cd ../contracts-ethers && yarn build && cd ../subgraph && yarn build", - "test": "cd ./packages/contracts && yarn test && cd ../subgraph && yarn test", - "clean": "cd ./packages/contracts && yarn clean && cd ../contracts-ethers && yarn clean && yarn clean && cd ../subgraph && yarn clean", + "build": "cd ./packages/contracts && yarn build && cd ../contracts-ethers && yarn build", + "test": "cd ./packages/contracts && yarn test", + "clean": "cd ./packages/contracts && yarn clean && cd ../contracts-ethers && yarn clean && yarn clean", "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"", "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"" } diff --git a/packages/contracts/deploy/01_repo/10_create_repo.ts b/packages/contracts/deploy/01_repo/10_create_repo.ts index ccf368b..c74ce51 100644 --- a/packages/contracts/deploy/01_repo/10_create_repo.ts +++ b/packages/contracts/deploy/01_repo/10_create_repo.ts @@ -1,6 +1,5 @@ import { - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, SpacePluginSetupParams, } from "../../plugin-setup-params"; @@ -23,10 +22,7 @@ const func: DeployFunction = function (hre: HardhatRuntimeEnvironment) { deployRepo(hre, PersonalSpaceAdminPluginSetupParams.PLUGIN_REPO_ENS_NAME) ) .then(() => - deployRepo(hre, MemberAccessPluginSetupParams.PLUGIN_REPO_ENS_NAME) - ) - .then(() => - deployRepo(hre, MainVotingPluginSetupParams.PLUGIN_REPO_ENS_NAME) + deployRepo(hre, GovernancePluginsSetupParams.PLUGIN_REPO_ENS_NAME) ); }; diff --git a/packages/contracts/deploy/02_setup/10_setup.ts b/packages/contracts/deploy/02_setup/10_setup.ts index 0c4f5a6..3b0fabc 100644 --- a/packages/contracts/deploy/02_setup/10_setup.ts +++ b/packages/contracts/deploy/02_setup/10_setup.ts @@ -1,6 +1,5 @@ import { - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, SpacePluginSetupParams, } from "../../plugin-setup-params"; @@ -23,7 +22,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { log: true, }); - // Space + // Personal Space console.log( `\nDeploying ${PersonalSpaceAdminPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME}`, ); @@ -37,23 +36,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, ); - // Space - console.log( - `\nDeploying ${MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME}`, - ); - - await deploy(MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, { - from: deployer, - args: [], - log: true, - }); - - // Space + // Governance console.log( - `\nDeploying ${MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME}`, + `\nDeploying ${GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME}`, ); - await deploy(MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, { + await deploy(GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME, { from: deployer, args: [], log: true, @@ -64,7 +52,6 @@ export default func; func.tags = [ SpacePluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, PersonalSpaceAdminPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, + GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME, "Deployment", ]; diff --git a/packages/contracts/deploy/02_setup/11_setup_conclude.ts b/packages/contracts/deploy/02_setup/11_setup_conclude.ts index 125ff76..12378d2 100644 --- a/packages/contracts/deploy/02_setup/11_setup_conclude.ts +++ b/packages/contracts/deploy/02_setup/11_setup_conclude.ts @@ -1,14 +1,12 @@ import { - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, SpacePluginSetupParams, } from "../../plugin-setup-params"; import { + GovernancePluginsSetup__factory, MainVotingPlugin__factory, - MainVotingPluginSetup__factory, MemberAccessPlugin__factory, - MemberAccessPluginSetup__factory, PersonalSpaceAdminPlugin__factory, PersonalSpaceAdminPluginSetup__factory, SpacePlugin__factory, @@ -21,8 +19,7 @@ import { setTimeout } from "timers/promises"; const func: DeployFunction = function (hre: HardhatRuntimeEnvironment) { return concludeSpaceSetup(hre) .then(() => concludePersonalSpaceVotingSetup(hre)) - .then(() => concludeMemberAccessVotingSetup(hre)) - .then(() => concludeMainVotingSetup(hre)); + .then(() => concludeGovernanceSetup(hre)); }; async function concludeSpaceSetup(hre: HardhatRuntimeEnvironment) { @@ -99,27 +96,31 @@ async function concludePersonalSpaceVotingSetup( }); } -async function concludeMemberAccessVotingSetup( +async function concludeGovernanceSetup( hre: HardhatRuntimeEnvironment, ) { const { deployments, network } = hre; const [deployer] = await hre.ethers.getSigners(); console.log( - `Concluding ${MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME} deployment.\n`, + `Concluding ${GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME} deployment.\n`, ); const setupDeployment = await deployments.get( - MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, + GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME, ); - const setup = MemberAccessPluginSetup__factory.connect( + const setup = GovernancePluginsSetup__factory.connect( setupDeployment.address, deployer, ); - const implementation = MemberAccessPlugin__factory.connect( + const mainVotingPluginImplementation = MainVotingPlugin__factory.connect( await setup.implementation(), deployer, ); + const memberAccessPluginImplementation = MemberAccessPlugin__factory.connect( + await setup.memberAccessPluginImplementation(), + deployer, + ); // Add a timeout for polygon because the call to `implementation()` can fail for newly deployed contracts in the first few seconds if (network.name === "polygon") { @@ -132,45 +133,11 @@ async function concludeMemberAccessVotingSetup( args: setupDeployment.args, }); hre.aragonToVerifyContracts.push({ - address: implementation.address, + address: mainVotingPluginImplementation.address, args: [], }); -} - -async function concludeMainVotingSetup( - hre: HardhatRuntimeEnvironment, -) { - const { deployments, network } = hre; - const [deployer] = await hre.ethers.getSigners(); - - console.log( - `Concluding ${MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME} deployment.\n`, - ); - - const setupDeployment = await deployments.get( - MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - ); - const setup = MainVotingPluginSetup__factory.connect( - setupDeployment.address, - deployer, - ); - const implementation = MainVotingPlugin__factory.connect( - await setup.implementation(), - deployer, - ); - - // Add a timeout for polygon because the call to `implementation()` can fail for newly deployed contracts in the first few seconds - if (network.name === "polygon") { - console.log(`Waiting 30secs for ${network.name} to finish up...`); - await setTimeout(30000); - } - - hre.aragonToVerifyContracts.push({ - address: setupDeployment.address, - args: setupDeployment.args, - }); hre.aragonToVerifyContracts.push({ - address: implementation.address, + address: memberAccessPluginImplementation.address, args: [], }); } @@ -179,7 +146,6 @@ export default func; func.tags = [ SpacePluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, PersonalSpaceAdminPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, + GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME, "Verification", ]; diff --git a/packages/contracts/deploy/02_setup/12_publish.ts b/packages/contracts/deploy/02_setup/12_publish.ts index dd711a8..d82fef1 100644 --- a/packages/contracts/deploy/02_setup/12_publish.ts +++ b/packages/contracts/deploy/02_setup/12_publish.ts @@ -1,6 +1,5 @@ import { - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, PluginSetupParams, SpacePluginSetupParams, @@ -19,8 +18,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; const func: DeployFunction = function (hre: HardhatRuntimeEnvironment) { return publishPlugin(hre, SpacePluginSetupParams) .then(() => publishPlugin(hre, PersonalSpaceAdminPluginSetupParams)) - .then(() => publishPlugin(hre, MemberAccessPluginSetupParams)) - .then(() => publishPlugin(hre, MainVotingPluginSetupParams)); + .then(() => publishPlugin(hre, GovernancePluginsSetupParams)); }; async function publishPlugin( @@ -150,7 +148,6 @@ export default func; func.tags = [ SpacePluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, PersonalSpaceAdminPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, - MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME, + GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME, "Publication", ]; diff --git a/packages/contracts/plugin-setup-params.ts b/packages/contracts/plugin-setup-params.ts index 2cfd8cb..5ed64fa 100644 --- a/packages/contracts/plugin-setup-params.ts +++ b/packages/contracts/plugin-setup-params.ts @@ -2,10 +2,8 @@ import spaceBuildMetadata from "./src/space-build-metadata.json"; import spaceReleaseMetadata from "./src/space-release-metadata.json"; import personalSpaceAdminBuildMetadata from "./src/personal-space-admin-build-metadata.json"; import personalSpaceAdminReleaseMetadata from "./src/personal-space-admin-release-metadata.json"; -import memberAccessBuildMetadata from "./src/member-access-build-metadata.json"; -import memberAccessReleaseMetadata from "./src/member-access-release-metadata.json"; -import mainVotingBuildMetadata from "./src/main-voting-build-metadata.json"; -import mainVotingReleaseMetadata from "./src/main-voting-release-metadata.json"; +import governanceBuildMetadata from "./src/governance-build-metadata.json"; +import governanceReleaseMetadata from "./src/governance-release-metadata.json"; export const SpacePluginSetupParams: PluginSetupParams = { PLUGIN_REPO_ENS_NAME: "geo-browser-space", @@ -35,31 +33,17 @@ export const PersonalSpaceAdminPluginSetupParams: PluginSetupParams = { }, }; -export const MemberAccessPluginSetupParams: PluginSetupParams = { - PLUGIN_REPO_ENS_NAME: "geo-browser-member-access-voting", - PLUGIN_CONTRACT_NAME: "MemberAccessPlugin", - PLUGIN_SETUP_CONTRACT_NAME: "MemberAccessPluginSetup", +export const GovernancePluginsSetupParams: PluginSetupParams = { + PLUGIN_REPO_ENS_NAME: "geo-browser-governance", + PLUGIN_CONTRACT_NAME: "MainVotingPlugin and MemberAccessPlugin", + PLUGIN_SETUP_CONTRACT_NAME: "GovernancePluginsSetup", VERSION: { release: 1, // Increment this number ONLY if breaking/incompatible changes were made. Updates between releases are NOT possible. build: 1, // Increment this number if non-breaking/compatible changes were made. Updates to newer builds are possible. }, METADATA: { - build: memberAccessBuildMetadata, - release: memberAccessReleaseMetadata, - }, -}; - -export const MainVotingPluginSetupParams: PluginSetupParams = { - PLUGIN_REPO_ENS_NAME: "geo-browser-main-voting", - PLUGIN_CONTRACT_NAME: "MainVotingPlugin", - PLUGIN_SETUP_CONTRACT_NAME: "MainVotingPluginSetup", - VERSION: { - release: 1, // Increment this number ONLY if breaking/incompatible changes were made. Updates between releases are NOT possible. - build: 1, // Increment this number if non-breaking/compatible changes were made. Updates to newer builds are possible. - }, - METADATA: { - build: mainVotingBuildMetadata, - release: mainVotingReleaseMetadata, + build: governanceBuildMetadata, + release: governanceReleaseMetadata, }, }; diff --git a/packages/contracts/src/GovernancePluginsSetup.sol b/packages/contracts/src/GovernancePluginsSetup.sol index 0ccd326..d4a7a72 100644 --- a/packages/contracts/src/GovernancePluginsSetup.sol +++ b/packages/contracts/src/GovernancePluginsSetup.sol @@ -13,12 +13,15 @@ import {MajorityVotingBase} from "@aragon/osx/plugins/governance/majority-voting /// @title GovernancePluginsSetup /// @dev Release 1, Build 1 contract GovernancePluginsSetup is PluginSetup { - address private immutable memberAccessPluginImplementation; address private immutable mainVotingPluginImplementation; + address public immutable memberAccessPluginImplementation; + + /// @notice Thrown when the array of helpers does not have the correct size + error InvalidHelpers(uint256 actualLength); constructor() { - memberAccessPluginImplementation = address(new MemberAccessPlugin()); mainVotingPluginImplementation = address(new MainVotingPlugin()); + memberAccessPluginImplementation = address(new MemberAccessPlugin()); } /// @inheritdoc IPluginSetup @@ -69,14 +72,14 @@ contract GovernancePluginsSetup is PluginSetup { permissions[0] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Grant, where: _dao, - who: mainVotingPluginImplementation, + who: mainVotingPlugin, condition: PermissionLib.NO_CONDITION, permissionId: DAO(payable(_dao)).EXECUTE_PERMISSION_ID() }); // The DAO can update the main voting plugin settings permissions[1] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Grant, - where: mainVotingPluginImplementation, + where: mainVotingPlugin, who: _dao, condition: PermissionLib.NO_CONDITION, permissionId: MainVotingPlugin(mainVotingPluginImplementation) @@ -85,7 +88,7 @@ contract GovernancePluginsSetup is PluginSetup { // The DAO can manage the list of addresses permissions[2] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Grant, - where: mainVotingPluginImplementation, + where: mainVotingPlugin, who: _dao, condition: PermissionLib.NO_CONDITION, permissionId: MainVotingPlugin(mainVotingPluginImplementation) @@ -94,7 +97,7 @@ contract GovernancePluginsSetup is PluginSetup { // The DAO can upgrade the main voting plugin permissions[3] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Grant, - where: mainVotingPluginImplementation, + where: mainVotingPlugin, who: _dao, condition: PermissionLib.NO_CONDITION, permissionId: MainVotingPlugin(mainVotingPluginImplementation) @@ -134,7 +137,7 @@ contract GovernancePluginsSetup is PluginSetup { if (_pluginUpgrader != address(0x0)) { permissions[7] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Grant, - where: mainVotingPluginImplementation, + where: mainVotingPlugin, who: _pluginUpgrader, condition: PermissionLib.NO_CONDITION, permissionId: MainVotingPlugin(mainVotingPluginImplementation) @@ -160,8 +163,13 @@ contract GovernancePluginsSetup is PluginSetup { address _dao, SetupPayload calldata _payload ) external view returns (PermissionLib.MultiTargetPermission[] memory permissionChanges) { + if (_payload.currentHelpers.length != 1) { + revert InvalidHelpers(_payload.currentHelpers.length); + } + // Decode incoming params address _pluginUpgrader = abi.decode(_payload.data, (address)); + address _memberAccessPlugin = _payload.currentHelpers[0]; permissionChanges = new PermissionLib.MultiTargetPermission[]( _pluginUpgrader == address(0x0) ? 7 : 9 @@ -211,14 +219,14 @@ contract GovernancePluginsSetup is PluginSetup { permissionChanges[4] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Revoke, where: _dao, - who: _payload.plugin, + who: _memberAccessPlugin, condition: PermissionLib.NO_CONDITION, permissionId: DAO(payable(_dao)).EXECUTE_PERMISSION_ID() }); // The DAO can no longer update the plugin settings permissionChanges[5] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Revoke, - where: _payload.plugin, + where: _memberAccessPlugin, who: _dao, condition: PermissionLib.NO_CONDITION, permissionId: MemberAccessPlugin(memberAccessPluginImplementation) @@ -227,7 +235,7 @@ contract GovernancePluginsSetup is PluginSetup { // The DAO can no longer upgrade the plugin permissionChanges[6] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Revoke, - where: _payload.plugin, + where: _memberAccessPlugin, who: _dao, condition: PermissionLib.NO_CONDITION, permissionId: MemberAccessPlugin(memberAccessPluginImplementation) @@ -246,7 +254,7 @@ contract GovernancePluginsSetup is PluginSetup { }); permissionChanges[8] = PermissionLib.MultiTargetPermission({ operation: PermissionLib.Operation.Revoke, - where: _payload.plugin, + where: _memberAccessPlugin, who: _pluginUpgrader, condition: PermissionLib.NO_CONDITION, permissionId: MemberAccessPlugin(memberAccessPluginImplementation) @@ -257,6 +265,6 @@ contract GovernancePluginsSetup is PluginSetup { /// @inheritdoc IPluginSetup function implementation() external view returns (address) { - return memberAccessPluginImplementation; + return mainVotingPluginImplementation; } } diff --git a/packages/contracts/test/integration-testing/deployment.ts b/packages/contracts/test/integration-testing/deployment.ts index e1f6f48..d280de0 100644 --- a/packages/contracts/test/integration-testing/deployment.ts +++ b/packages/contracts/test/integration-testing/deployment.ts @@ -1,13 +1,8 @@ -import { - PluginRepo, - SpacePluginSetup, - SpacePluginSetup__factory, -} from "../../typechain"; +import { PluginRepo } from "../../typechain"; import { osxContracts } from "../../utils/helpers"; import { getPluginRepoInfo } from "../../utils/plugin-repo-info"; import { - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, SpacePluginSetupParams, } from "../../plugin-setup-params"; @@ -39,8 +34,7 @@ describe("PluginRepo Deployment", function () { }); const setups = [ - MainVotingPluginSetupParams, - MemberAccessPluginSetupParams, + GovernancePluginsSetupParams, PersonalSpaceAdminPluginSetupParams, SpacePluginSetupParams, ]; @@ -125,15 +119,9 @@ describe("PluginRepo Deployment", function () { ); break; - case MemberAccessPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME: - expect(receivedStriMetadata).to.equal( - "ipfs://Qmd6LmivjWNMisxMKqZgmD9HasnQq2JngKJH3WTmqMjCNn", - ); - break; - - case MainVotingPluginSetupParams.PLUGIN_SETUP_CONTRACT_NAME: + case GovernancePluginsSetupParams.PLUGIN_SETUP_CONTRACT_NAME: expect(receivedStriMetadata).to.equal( - "ipfs://QmNxhDLP2FL8vUJwUq8pKrLg1AGSKdgwopS6tQb5Gy7VSg", + "ipfs://QmNh5KHv167RKZgD8zb6d3CvRE7mNT8AZYZkwrmvyRt1YD", ); break; diff --git a/packages/contracts/test/integration-testing/main-voting-setup.ts b/packages/contracts/test/integration-testing/governance-plugins-setup.ts similarity index 84% rename from packages/contracts/test/integration-testing/main-voting-setup.ts rename to packages/contracts/test/integration-testing/governance-plugins-setup.ts index 0e8b301..decdc23 100644 --- a/packages/contracts/test/integration-testing/main-voting-setup.ts +++ b/packages/contracts/test/integration-testing/governance-plugins-setup.ts @@ -1,9 +1,9 @@ -import { MainVotingPluginSetupParams } from "../../plugin-setup-params"; +import { GovernancePluginsSetupParams } from "../../plugin-setup-params"; import { + GovernancePluginsSetup, + GovernancePluginsSetup__factory, MainVotingPlugin, MainVotingPlugin__factory, - MainVotingPluginSetup, - MainVotingPluginSetup__factory, MajorityVotingBase, PluginRepo, } from "../../typechain"; @@ -25,7 +25,7 @@ import { BigNumber } from "ethers"; import { ethers } from "hardhat"; import { ADDRESS_ZERO } from "../unit-testing/common"; -describe("MainVotingPluginSetup processing", function () { +describe("GovernancePluginsSetup processing", function () { let alice: SignerWithAddress; let psp: PluginSetupProcessor; @@ -38,7 +38,7 @@ describe("MainVotingPluginSetup processing", function () { const hardhatForkNetwork = process.env.NETWORK_NAME ?? "mainnet"; const pluginRepoInfo = getPluginRepoInfo( - MainVotingPluginSetupParams.PLUGIN_REPO_ENS_NAME, + GovernancePluginsSetupParams.PLUGIN_REPO_ENS_NAME, "hardhat", ); if (!pluginRepoInfo) { @@ -82,7 +82,7 @@ describe("MainVotingPluginSetup processing", function () { }); context("Build 1", async () => { - let setup: MainVotingPluginSetup; + let setup: GovernancePluginsSetup; let pluginSetupRef: PluginSetupRefStruct; let plugin: MainVotingPlugin; const pluginUpgrader = ADDRESS_ZERO; @@ -91,7 +91,7 @@ describe("MainVotingPluginSetup processing", function () { const release = 1; // Deploy setups. - setup = MainVotingPluginSetup__factory.connect( + setup = GovernancePluginsSetup__factory.connect( (await pluginRepo["getLatestVersion(uint8)"](release)).pluginSetup, alice, ); @@ -113,15 +113,21 @@ describe("MainVotingPluginSetup processing", function () { minProposerVotingPower: 0, votingMode: 0, }; + const minMemberAccessProposalDuration = 60 * 60 * 24; // Install build 1. const data = ethers.utils.defaultAbiCoder.encode( getNamedTypesFromMetadata( - MainVotingPluginSetupParams.METADATA.build.pluginSetup + GovernancePluginsSetupParams.METADATA.build.pluginSetup .prepareInstallation .inputs, ), - [settings, [alice.address], pluginUpgrader], + [ + settings, + [alice.address], + minMemberAccessProposalDuration, + pluginUpgrader, + ], ); const results = await installPlugin(psp, dao, pluginSetupRef, data); @@ -140,7 +146,7 @@ describe("MainVotingPluginSetup processing", function () { // Uninstall build 1. const data = ethers.utils.defaultAbiCoder.encode( getNamedTypesFromMetadata( - MainVotingPluginSetupParams.METADATA.build.pluginSetup + GovernancePluginsSetupParams.METADATA.build.pluginSetup .prepareUninstallation .inputs, ), diff --git a/packages/contracts/test/integration-testing/member-access-setup.ts b/packages/contracts/test/integration-testing/member-access-setup.ts deleted file mode 100644 index 394fb86..0000000 --- a/packages/contracts/test/integration-testing/member-access-setup.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { MemberAccessPluginSetupParams } from "../../plugin-setup-params"; -import { - MainVotingPlugin__factory, - MajorityVotingBase, - MemberAccessPlugin, - MemberAccessPlugin__factory, - MemberAccessPluginSetup, - MemberAccessPluginSetup__factory, - PluginRepo, -} from "../../typechain"; -import { PluginSetupRefStruct } from "../../typechain/@aragon/osx/framework/dao/DAOFactory"; -import { osxContracts } from "../../utils/helpers"; -import { getPluginRepoInfo } from "../../utils/plugin-repo-info"; -import { installPlugin, uninstallPlugin } from "../helpers/setup"; -import { deployTestDao } from "../helpers/test-dao"; -import { getNamedTypesFromMetadata } from "../helpers/types"; -import { - DAO, - PluginRepo__factory, - PluginSetupProcessor, - PluginSetupProcessor__factory, -} from "@aragon/osx-ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { expect } from "chai"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; -import { ADDRESS_ZERO } from "../unit-testing/common"; - -describe("MemberAccessPluginSetup processing", function () { - let alice: SignerWithAddress; - - let psp: PluginSetupProcessor; - let dao: DAO; - let pluginRepo: PluginRepo; - - before(async () => { - [alice] = await ethers.getSigners(); - - const hardhatForkNetwork = process.env.NETWORK_NAME ?? "mainnet"; - - const pluginRepoInfo = getPluginRepoInfo( - MemberAccessPluginSetupParams.PLUGIN_REPO_ENS_NAME, - "hardhat", - ); - if (!pluginRepoInfo) { - throw new Error("The plugin setup details are not available"); - } - - // PSP - psp = PluginSetupProcessor__factory.connect( - osxContracts[hardhatForkNetwork]["PluginSetupProcessor"], - alice, - ); - - // Deploy DAO. - dao = await deployTestDao(alice); - - await dao.grant( - dao.address, - psp.address, - ethers.utils.id("ROOT_PERMISSION"), - ); - await dao.grant( - psp.address, - alice.address, - ethers.utils.id("APPLY_INSTALLATION_PERMISSION"), - ); - await dao.grant( - psp.address, - alice.address, - ethers.utils.id("APPLY_UNINSTALLATION_PERMISSION"), - ); - await dao.grant( - psp.address, - alice.address, - ethers.utils.id("APPLY_UPDATE_PERMISSION"), - ); - - pluginRepo = PluginRepo__factory.connect( - pluginRepoInfo.address, - alice, - ); - }); - - context("Build 1", async () => { - let setup: MemberAccessPluginSetup; - let pluginSetupRef: PluginSetupRefStruct; - let plugin: MemberAccessPlugin; - const pluginUpgrader = ADDRESS_ZERO; - - before(async () => { - const release = 1; - - // Deploy setups. - setup = MemberAccessPluginSetup__factory.connect( - (await pluginRepo["getLatestVersion(uint8)"](release)).pluginSetup, - alice, - ); - - pluginSetupRef = { - versionTag: { - release: BigNumber.from(release), - build: BigNumber.from(1), - }, - pluginSetupRepo: pluginRepo.address, - }; - }); - - beforeEach(async () => { - // dependency - const mainVotingPlugin = await new MainVotingPlugin__factory(alice) - .deploy(); - - const settings: MemberAccessPlugin.MultisigSettingsStruct = { - mainVotingPlugin: mainVotingPlugin.address, - proposalDuration: 60 * 60 * 24, - }; - - // Install build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - MemberAccessPluginSetupParams.METADATA.build.pluginSetup - .prepareInstallation - .inputs, - ), - [settings, pluginUpgrader], - ); - const results = await installPlugin(psp, dao, pluginSetupRef, data); - - plugin = MemberAccessPlugin__factory.connect( - results.preparedEvent.args.plugin, - alice, - ); - }); - - it("installs & uninstalls", async () => { - expect(await plugin.implementation()).to.be.eq( - await setup.implementation(), - ); - expect(await plugin.dao()).to.be.eq(dao.address); - - // Uninstall build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - MemberAccessPluginSetupParams.METADATA.build.pluginSetup - .prepareUninstallation - .inputs, - ), - [pluginUpgrader], - ); - await uninstallPlugin(psp, dao, plugin, pluginSetupRef, data, []); - }); - }); -}); diff --git a/packages/contracts/test/unit-testing/main-voting-plugin-setup.ts b/packages/contracts/test/unit-testing/governance-plugins-setup.ts similarity index 50% rename from packages/contracts/test/unit-testing/main-voting-plugin-setup.ts rename to packages/contracts/test/unit-testing/governance-plugins-setup.ts index 448a523..f06701f 100644 --- a/packages/contracts/test/unit-testing/main-voting-plugin-setup.ts +++ b/packages/contracts/test/unit-testing/governance-plugins-setup.ts @@ -1,9 +1,9 @@ -import buildMetadata from "../../src/main-voting-build-metadata.json"; +import buildMetadata from "../../src/governance-build-metadata.json"; import { DAO, + GovernancePluginsSetup, + GovernancePluginsSetup__factory, MainVotingPlugin__factory, - MainVotingPluginSetup, - MainVotingPluginSetup__factory, } from "../../typechain"; import { deployTestDao } from "../helpers/test-dao"; import { getNamedTypesFromMetadata, Operation } from "../helpers/types"; @@ -15,6 +15,7 @@ import { NO_CONDITION, pctToRatio, UPDATE_ADDRESSES_PERMISSION_ID, + UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, UPDATE_VOTING_SETTINGS_PERMISSION_ID, UPGRADE_PLUGIN_PERMISSION_ID, VotingMode, @@ -23,17 +24,17 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { ethers } from "hardhat"; -describe("Main Voting Plugin Setup", function () { +describe("Governance Plugins Setup", function () { let alice: SignerWithAddress; let bob: SignerWithAddress; - let mainVotingPluginSetup: MainVotingPluginSetup; + let governancePluginsSetup: GovernancePluginsSetup; let dao: DAO; before(async () => { [alice, bob] = await ethers.getSigners(); dao = await deployTestDao(alice); - mainVotingPluginSetup = await new MainVotingPluginSetup__factory(alice) + governancePluginsSetup = await new GovernancePluginsSetup__factory(alice) .deploy(); }); @@ -55,62 +56,97 @@ describe("Main Voting Plugin Setup", function () { minProposerVotingPower: 0, }, [alice.address], + 60 * 60 * 24, pluginUpgrader, ], ); const nonce = await ethers.provider.getTransactionCount( - mainVotingPluginSetup.address, + governancePluginsSetup.address, ); - const anticipatedPluginAddress = ethers.utils.getContractAddress({ - from: mainVotingPluginSetup.address, - nonce, - }); + const anticipatedMainVotingPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce, + }); + const anticipatedMemberAccessPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce: nonce + 1, + }); + const anticipatedConditionPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce: nonce + 2, + }); const { - plugin, + mainVotingPlugin, preparedSetupData: { helpers, permissions }, - } = await mainVotingPluginSetup.callStatic.prepareInstallation( + } = await governancePluginsSetup.callStatic.prepareInstallation( dao.address, initData, ); + expect(mainVotingPlugin).to.be.equal(anticipatedMainVotingPluginAddress); + expect(helpers.length).to.be.equal(1); + const [memberAccessPlugin] = helpers; + expect(memberAccessPlugin).to.eq(anticipatedMemberAccessPluginAddress); - expect(plugin).to.be.equal(anticipatedPluginAddress); - expect(helpers.length).to.be.equal(0); - expect(permissions.length).to.be.equal(4); + expect(permissions.length).to.be.equal(7); expect(permissions).to.deep.equal([ [ Operation.Grant, dao.address, - plugin, + mainVotingPlugin, NO_CONDITION, EXECUTE_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, dao.address, NO_CONDITION, UPDATE_VOTING_SETTINGS_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, dao.address, NO_CONDITION, UPDATE_ADDRESSES_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, + dao.address, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Grant, + dao.address, + memberAccessPlugin, + anticipatedConditionPluginAddress, + EXECUTE_PERMISSION_ID, + ], + [ + Operation.Grant, + memberAccessPlugin, + dao.address, + NO_CONDITION, + UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, + ], + [ + Operation.Grant, + memberAccessPlugin, dao.address, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, ], ]); - await mainVotingPluginSetup.prepareInstallation(dao.address, initData); + await governancePluginsSetup.prepareInstallation(dao.address, initData); const myPlugin = new MainVotingPlugin__factory(alice).attach( - plugin, + mainVotingPlugin, ); // initialization is correct @@ -135,69 +171,111 @@ describe("Main Voting Plugin Setup", function () { minProposerVotingPower: 0, }, [alice.address], + 60 * 60 * 24, pluginUpgrader, ], ); const nonce = await ethers.provider.getTransactionCount( - mainVotingPluginSetup.address, + governancePluginsSetup.address, ); - const anticipatedPluginAddress = ethers.utils.getContractAddress({ - from: mainVotingPluginSetup.address, - nonce, - }); + const anticipatedMainVotingPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce, + }); + const anticipatedMemberAccessPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce: nonce + 1, + }); + const anticipatedConditionPluginAddress = ethers.utils + .getContractAddress({ + from: governancePluginsSetup.address, + nonce: nonce + 2, + }); const { - plugin, + mainVotingPlugin, preparedSetupData: { helpers, permissions }, - } = await mainVotingPluginSetup.callStatic.prepareInstallation( + } = await governancePluginsSetup.callStatic.prepareInstallation( dao.address, initData, ); + expect(mainVotingPlugin).to.be.equal(anticipatedMainVotingPluginAddress); + expect(helpers.length).to.be.equal(1); + const [memberAccessPlugin] = helpers; + expect(memberAccessPlugin).to.eq(anticipatedMemberAccessPluginAddress); - expect(plugin).to.be.equal(anticipatedPluginAddress); - expect(helpers.length).to.be.equal(0); - expect(permissions.length).to.be.equal(5); + expect(permissions.length).to.be.equal(9); expect(permissions).to.deep.equal([ [ Operation.Grant, dao.address, - plugin, + mainVotingPlugin, NO_CONDITION, EXECUTE_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, dao.address, NO_CONDITION, UPDATE_VOTING_SETTINGS_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, dao.address, NO_CONDITION, UPDATE_ADDRESSES_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, + dao.address, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Grant, + dao.address, + memberAccessPlugin, + anticipatedConditionPluginAddress, + EXECUTE_PERMISSION_ID, + ], + [ + Operation.Grant, + memberAccessPlugin, + dao.address, + NO_CONDITION, + UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, + ], + [ + Operation.Grant, + memberAccessPlugin, dao.address, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, ], [ Operation.Grant, - plugin, + mainVotingPlugin, + pluginUpgrader, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Grant, + memberAccessPlugin, pluginUpgrader, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, ], ]); - await mainVotingPluginSetup.prepareInstallation(dao.address, initData); + await governancePluginsSetup.prepareInstallation(dao.address, initData); const myPlugin = new MainVotingPlugin__factory(alice).attach( - plugin, + mainVotingPlugin, ); // initialization is correct @@ -208,7 +286,10 @@ describe("Main Voting Plugin Setup", function () { describe("prepareUninstallation", async () => { it("returns the permissions (no pluginUpgrader)", async () => { - const plugin = await new MainVotingPlugin__factory(alice).deploy(); + const mainVotingPlugin = await new MainVotingPlugin__factory(alice) + .deploy(); + const memberAccessPlugin = await new MainVotingPlugin__factory(alice) + .deploy(); const pluginUpgrader = ADDRESS_ZERO; const uninstallData = abiCoder.encode( @@ -217,42 +298,63 @@ describe("Main Voting Plugin Setup", function () { ), [pluginUpgrader], ); - const permissions = await mainVotingPluginSetup.callStatic + const permissions = await governancePluginsSetup.callStatic .prepareUninstallation( dao.address, { - plugin: plugin.address, - currentHelpers: [], + plugin: mainVotingPlugin.address, + currentHelpers: [memberAccessPlugin.address], data: uninstallData, }, ); - expect(permissions.length).to.be.equal(4); + expect(permissions.length).to.be.equal(7); expect(permissions).to.deep.equal([ [ Operation.Revoke, dao.address, - plugin.address, + mainVotingPlugin.address, NO_CONDITION, EXECUTE_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, dao.address, NO_CONDITION, UPDATE_VOTING_SETTINGS_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, dao.address, NO_CONDITION, UPDATE_ADDRESSES_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, + dao.address, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Revoke, + dao.address, + memberAccessPlugin.address, + NO_CONDITION, + EXECUTE_PERMISSION_ID, + ], + [ + Operation.Revoke, + memberAccessPlugin.address, + dao.address, + NO_CONDITION, + UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, + ], + [ + Operation.Revoke, + memberAccessPlugin.address, dao.address, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, @@ -260,8 +362,11 @@ describe("Main Voting Plugin Setup", function () { ]); }); - it("returns the permissions (no pluginUpgrader)", async () => { - const plugin = await new MainVotingPlugin__factory(alice).deploy(); + it("returns the permissions (with a pluginUpgrader)", async () => { + const mainVotingPlugin = await new MainVotingPlugin__factory(alice) + .deploy(); + const memberAccessPlugin = await new MainVotingPlugin__factory(alice) + .deploy(); const pluginUpgrader = bob.address; const uninstallData = abiCoder.encode( @@ -270,49 +375,77 @@ describe("Main Voting Plugin Setup", function () { ), [pluginUpgrader], ); - const permissions = await mainVotingPluginSetup.callStatic + const permissions = await governancePluginsSetup.callStatic .prepareUninstallation( dao.address, { - plugin: plugin.address, - currentHelpers: [], + plugin: mainVotingPlugin.address, + currentHelpers: [memberAccessPlugin.address], data: uninstallData, }, ); - expect(permissions.length).to.be.equal(5); + expect(permissions.length).to.be.equal(9); expect(permissions).to.deep.equal([ [ Operation.Revoke, dao.address, - plugin.address, + mainVotingPlugin.address, NO_CONDITION, EXECUTE_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, dao.address, NO_CONDITION, UPDATE_VOTING_SETTINGS_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, dao.address, NO_CONDITION, UPDATE_ADDRESSES_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + mainVotingPlugin.address, dao.address, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, ], [ Operation.Revoke, - plugin.address, + dao.address, + memberAccessPlugin.address, + NO_CONDITION, + EXECUTE_PERMISSION_ID, + ], + [ + Operation.Revoke, + memberAccessPlugin.address, + dao.address, + NO_CONDITION, + UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, + ], + [ + Operation.Revoke, + memberAccessPlugin.address, + dao.address, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Revoke, + mainVotingPlugin.address, + pluginUpgrader, + NO_CONDITION, + UPGRADE_PLUGIN_PERMISSION_ID, + ], + [ + Operation.Revoke, + memberAccessPlugin.address, pluginUpgrader, NO_CONDITION, UPGRADE_PLUGIN_PERMISSION_ID, diff --git a/packages/contracts/test/unit-testing/member-access-plugin-setup.ts b/packages/contracts/test/unit-testing/member-access-plugin-setup.ts deleted file mode 100644 index 9d91e8d..0000000 --- a/packages/contracts/test/unit-testing/member-access-plugin-setup.ts +++ /dev/null @@ -1,302 +0,0 @@ -import buildMetadata from "../../src/member-access-build-metadata.json"; -import { - DAO, - MainVotingPlugin, - MainVotingPlugin__factory, - MemberAccessPlugin__factory, - MemberAccessPluginSetup, - MemberAccessPluginSetup__factory, -} from "../../typechain"; -import { deployWithProxy } from "../../utils/helpers"; -import { deployTestDao } from "../helpers/test-dao"; -import { getNamedTypesFromMetadata, Operation } from "../helpers/types"; -import { - abiCoder, - ADDRESS_ZERO, - EDITOR_PERMISSION_ID, - EXECUTE_PERMISSION_ID, - NO_CONDITION, - UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, - UPGRADE_PLUGIN_PERMISSION_ID, -} from "./common"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "hardhat"; - -describe("Member Access Plugin Setup", function () { - let alice: SignerWithAddress; - let bob: SignerWithAddress; - let memberAccessPluginSetup: MemberAccessPluginSetup; - let mainVotingPlugin: MainVotingPlugin; - let dao: DAO; - - before(async () => { - [alice, bob] = await ethers.getSigners(); - dao = await deployTestDao(alice); - - mainVotingPlugin = await deployWithProxy( - new MainVotingPlugin__factory(alice), - ); - await dao.grant( - mainVotingPlugin.address, - alice.address, - EDITOR_PERMISSION_ID, - ).then((tx) => tx.wait()); - await mainVotingPlugin.initialize(dao.address, { - minDuration: 60 * 60 * 24 * 5, - minParticipation: 50000, - minProposerVotingPower: 0, - supportThreshold: 300000, - votingMode: 0, - }, [alice.address]).then((tx) => tx.wait()); - - memberAccessPluginSetup = await new MemberAccessPluginSetup__factory(alice) - .deploy(); - }); - - describe("prepareInstallation", async () => { - it("returns the plugin, helpers, and permissions (no pluginUpgrader)", async () => { - const pluginUpgrader = ADDRESS_ZERO; - const initData = abiCoder.encode( - getNamedTypesFromMetadata( - buildMetadata.pluginSetup.prepareInstallation.inputs, - ), - [{ - proposalDuration: 60 * 60 * 24 * 5, - mainVotingPlugin: mainVotingPlugin.address, - }, pluginUpgrader], - ); - - const nonce = await ethers.provider.getTransactionCount( - memberAccessPluginSetup.address, - ); - const anticipatedPluginAddress = ethers.utils.getContractAddress({ - from: memberAccessPluginSetup.address, - nonce, - }); - - const { - plugin, - preparedSetupData: { helpers, permissions }, - } = await memberAccessPluginSetup.callStatic.prepareInstallation( - dao.address, - initData, - ); - - const anticipatedConditionAddress = ethers.utils.getContractAddress({ - from: memberAccessPluginSetup.address, - nonce: nonce + 1, - }); - - expect(plugin).to.be.equal(anticipatedPluginAddress); - expect(helpers.length).to.be.equal(0); - expect(permissions.length).to.be.equal(3); - expect(permissions).to.deep.equal([ - [ - Operation.Grant, - dao.address, - plugin, - anticipatedConditionAddress, - EXECUTE_PERMISSION_ID, - ], - [ - Operation.Grant, - plugin, - dao.address, - NO_CONDITION, - UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, - ], - [ - Operation.Grant, - plugin, - dao.address, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - ]); - - await memberAccessPluginSetup.prepareInstallation(dao.address, initData); - const myPlugin = new MemberAccessPlugin__factory(alice).attach( - plugin, - ); - - // initialization is correct - expect(await myPlugin.dao()).to.eq(dao.address); - }); - - it("returns the plugin, helpers, and permissions (with a pluginUpgrader)", async () => { - const pluginUpgrader = bob.address; - const initData = abiCoder.encode( - getNamedTypesFromMetadata( - buildMetadata.pluginSetup.prepareInstallation.inputs, - ), - [{ - proposalDuration: 60 * 60 * 24 * 5, - mainVotingPlugin: mainVotingPlugin.address, - }, pluginUpgrader], - ); - const nonce = await ethers.provider.getTransactionCount( - memberAccessPluginSetup.address, - ); - const anticipatedPluginAddress = ethers.utils.getContractAddress({ - from: memberAccessPluginSetup.address, - nonce, - }); - const anticipatedConditionAddress = ethers.utils.getContractAddress({ - from: memberAccessPluginSetup.address, - nonce: nonce + 1, - }); - - const { - plugin, - preparedSetupData: { helpers, permissions }, - } = await memberAccessPluginSetup.callStatic.prepareInstallation( - dao.address, - initData, - ); - - expect(plugin).to.be.equal(anticipatedPluginAddress); - expect(helpers.length).to.be.equal(0); - expect(permissions.length).to.be.equal(4); - expect(permissions).to.deep.equal([ - [ - Operation.Grant, - dao.address, - plugin, - anticipatedConditionAddress, - EXECUTE_PERMISSION_ID, - ], - [ - Operation.Grant, - plugin, - dao.address, - NO_CONDITION, - UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, - ], - [ - Operation.Grant, - plugin, - dao.address, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - [ - Operation.Grant, - plugin, - pluginUpgrader, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - ]); - - await memberAccessPluginSetup.prepareInstallation(dao.address, initData); - const myPlugin = new MemberAccessPlugin__factory(alice).attach( - plugin, - ); - - // initialization is correct - expect(await myPlugin.dao()).to.eq(dao.address); - }); - }); - - describe("prepareUninstallation", async () => { - it("returns the permissions (no pluginUpgrader)", async () => { - const plugin = await new MemberAccessPlugin__factory(alice).deploy(); - - const uninstallData = abiCoder.encode( - getNamedTypesFromMetadata( - buildMetadata.pluginSetup.prepareUninstallation.inputs, - ), - [ADDRESS_ZERO], - ); - const permissions = await memberAccessPluginSetup.callStatic - .prepareUninstallation( - dao.address, - { - plugin: plugin.address, - currentHelpers: [], - data: uninstallData, - }, - ); - - expect(permissions.length).to.be.equal(3); - expect(permissions).to.deep.equal([ - [ - Operation.Revoke, - dao.address, - plugin.address, - NO_CONDITION, - EXECUTE_PERMISSION_ID, - ], - [ - Operation.Revoke, - plugin.address, - dao.address, - NO_CONDITION, - UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, - ], - [ - Operation.Revoke, - plugin.address, - dao.address, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - ]); - }); - - it("returns the permissions (with a pluginUpgrader)", async () => { - const plugin = await new MemberAccessPlugin__factory(alice).deploy(); - - const pluginUpgrader = bob.address; - const uninstallData = abiCoder.encode( - getNamedTypesFromMetadata( - buildMetadata.pluginSetup.prepareUninstallation.inputs, - ), - [pluginUpgrader], - ); - - const permissions = await memberAccessPluginSetup.callStatic - .prepareUninstallation( - dao.address, - { - plugin: plugin.address, - currentHelpers: [], - data: uninstallData, - }, - ); - - expect(permissions.length).to.be.equal(4); - expect(permissions).to.deep.equal([ - [ - Operation.Revoke, - dao.address, - plugin.address, - NO_CONDITION, - EXECUTE_PERMISSION_ID, - ], - [ - Operation.Revoke, - plugin.address, - dao.address, - NO_CONDITION, - UPDATE_MULTISIG_SETTINGS_PERMISSION_ID, - ], - [ - Operation.Revoke, - plugin.address, - dao.address, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - [ - Operation.Revoke, - plugin.address, - pluginUpgrader, - NO_CONDITION, - UPGRADE_PLUGIN_PERMISSION_ID, - ], - ]); - }); - }); -});