From 833f1ae32d8794273f29b1ac9ecae8a227747a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Wed, 8 Nov 2023 12:49:44 +0100 Subject: [PATCH] Ready --- README.md | 19 ++++--- .../contracts/src/GovernancePluginsSetup.sol | 53 ++++++++++++++++++- .../src/PersonalSpaceAdminPluginSetup.sol | 14 ++++- packages/contracts/src/SpacePluginSetup.sol | 45 +++++++++++++++- .../governance-plugins-setup.ts | 26 +++------ .../personal-space-admin-setup.ts | 25 +++------ .../test/integration-testing/space-setup.ts | 20 ++----- 7 files changed, 138 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index a4f1769..1a7cd63 100644 --- a/README.md +++ b/README.md @@ -444,7 +444,7 @@ 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 +### Plugin Setup install parameters In both of the cases described above, a call to `prepareInstallation()` will be made by the `PluginSetupProcessor` from OSx. @@ -456,20 +456,25 @@ function prepareInstallation( ``` - 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 second parameter contains an arbitrary array of bytes, with the ABI encoded custom settings that the plugin setup needs to operate. -The first step for `prepareInstallation()` is to decode them and use them on the deployment script as needed: +Convenience functions are provided within the plugin setup contracts: ```solidity -// Decode incoming params -( +// SpacePluginSetup.sol + +function encodeInstallationParams( string memory _firstBlockContentUri, address _predecessorAddress, address _pluginUpgrader -) = abi.decode(_data, (string, address, address)); +) public pure returns (bytes memory); + +function encodeUninstallationParams( + address _pluginUpgrader +) public pure returns (bytes memory) ``` -The JSON encoded ABI definition can be found at the corresponding `-build-metadata.json` file: +The JSON encoded ABI definition can also be found at the corresponding `-build-metadata.json` file: ```json { diff --git a/packages/contracts/src/GovernancePluginsSetup.sol b/packages/contracts/src/GovernancePluginsSetup.sol index d4a7a72..5945b05 100644 --- a/packages/contracts/src/GovernancePluginsSetup.sol +++ b/packages/contracts/src/GovernancePluginsSetup.sol @@ -36,7 +36,7 @@ contract GovernancePluginsSetup is PluginSetup { address[] memory _initialEditors, uint64 _memberAccessProposalDuration, address _pluginUpgrader - ) = abi.decode(_data, (MajorityVotingBase.VotingSettings, address[], uint64, address)); + ) = decodeInstallationParams(_data); // Deploy the main voting plugin mainVotingPlugin = createERC1967Proxy( @@ -168,7 +168,7 @@ contract GovernancePluginsSetup is PluginSetup { } // Decode incoming params - address _pluginUpgrader = abi.decode(_payload.data, (address)); + address _pluginUpgrader = decodeUninstallationParams(_payload.data); address _memberAccessPlugin = _payload.currentHelpers[0]; permissionChanges = new PermissionLib.MultiTargetPermission[]( @@ -267,4 +267,53 @@ contract GovernancePluginsSetup is PluginSetup { function implementation() external view returns (address) { return mainVotingPluginImplementation; } + + /// @notice Encodes the given installation parameters into a byte array + function encodeInstallationParams( + MajorityVotingBase.VotingSettings calldata _votingSettings, + address[] calldata _initialEditors, + uint64 _memberAccessProposalDuration, + address _pluginUpgrader + ) public pure returns (bytes memory) { + return + abi.encode( + _votingSettings, + _initialEditors, + _memberAccessProposalDuration, + _pluginUpgrader + ); + } + + /// @notice Decodes the given byte array into the original installation parameters + function decodeInstallationParams( + bytes memory _data + ) + public + pure + returns ( + MajorityVotingBase.VotingSettings memory votingSettings, + address[] memory initialEditors, + uint64 memberAccessProposalDuration, + address pluginUpgrader + ) + { + (votingSettings, initialEditors, memberAccessProposalDuration, pluginUpgrader) = abi.decode( + _data, + (MajorityVotingBase.VotingSettings, address[], uint64, address) + ); + } + + /// @notice Encodes the given uninstallation parameters into a byte array + function encodeUninstallationParams( + address _pluginUpgrader + ) public pure returns (bytes memory) { + return abi.encode(_pluginUpgrader); + } + + /// @notice Decodes the given byte array into the original uninstallation parameters + function decodeUninstallationParams( + bytes memory _data + ) public pure returns (address pluginUpgrader) { + (pluginUpgrader) = abi.decode(_data, (address)); + } } diff --git a/packages/contracts/src/PersonalSpaceAdminPluginSetup.sol b/packages/contracts/src/PersonalSpaceAdminPluginSetup.sol index cf58926..cbe3302 100644 --- a/packages/contracts/src/PersonalSpaceAdminPluginSetup.sol +++ b/packages/contracts/src/PersonalSpaceAdminPluginSetup.sol @@ -35,7 +35,7 @@ contract PersonalSpaceAdminPluginSetup is PluginSetup { bytes calldata _data ) external returns (address plugin, PreparedSetupData memory preparedSetupData) { // Decode `_data` to extract the params needed for cloning and initializing the `PersonalSpaceAdminPlugin` plugin. - address editor = abi.decode(_data, (address)); + address editor = decodeInstallationParams(_data); if (editor == address(0)) { revert EditorAddressInvalid({editor: editor}); @@ -95,4 +95,16 @@ contract PersonalSpaceAdminPluginSetup is PluginSetup { function implementation() external view returns (address) { return implementation_; } + + /// @notice Encodes the given installation parameters into a byte array + function encodeInstallationParams(address _initialEditor) public pure returns (bytes memory) { + return abi.encode(_initialEditor); + } + + /// @notice Decodes the given byte array into the original installation parameters + function decodeInstallationParams( + bytes memory _data + ) public pure returns (address initialEditor) { + (initialEditor) = abi.decode(_data, (address)); + } } diff --git a/packages/contracts/src/SpacePluginSetup.sol b/packages/contracts/src/SpacePluginSetup.sol index 1f5c99a..06d8e8a 100644 --- a/packages/contracts/src/SpacePluginSetup.sol +++ b/packages/contracts/src/SpacePluginSetup.sol @@ -26,7 +26,7 @@ contract SpacePluginSetup is PluginSetup { string memory _firstBlockContentUri, address _predecessorAddress, address _pluginUpgrader - ) = abi.decode(_data, (string, address, address)); + ) = decodeInstallationParams(_data); // Deploy new plugin instance plugin = createERC1967Proxy( @@ -90,7 +90,7 @@ contract SpacePluginSetup is PluginSetup { SetupPayload calldata _payload ) external view returns (PermissionLib.MultiTargetPermission[] memory permissionChanges) { // Decode incoming params - address _pluginUpgrader = abi.decode(_payload.data, (address)); + address _pluginUpgrader = decodeUninstallationParams(_payload.data); permissionChanges = new PermissionLib.MultiTargetPermission[]( _pluginUpgrader == address(0x0) ? 3 : 4 @@ -134,4 +134,45 @@ contract SpacePluginSetup is PluginSetup { function implementation() external view returns (address) { return pluginImplementation; } + + /// @notice Encodes the given installation parameters into a byte array + function encodeInstallationParams( + string memory _firstBlockContentUri, + address _predecessorAddress, + address _pluginUpgrader + ) public pure returns (bytes memory) { + return abi.encode(_firstBlockContentUri, _predecessorAddress, _pluginUpgrader); + } + + /// @notice Decodes the given byte array into the original installation parameters + function decodeInstallationParams( + bytes memory _data + ) + public + pure + returns ( + string memory firstBlockContentUri, + address predecessorAddress, + address pluginUpgrader + ) + { + (firstBlockContentUri, predecessorAddress, pluginUpgrader) = abi.decode( + _data, + (string, address, address) + ); + } + + /// @notice Encodes the given uninstallation parameters into a byte array + function encodeUninstallationParams( + address _pluginUpgrader + ) public pure returns (bytes memory) { + return abi.encode(_pluginUpgrader); + } + + /// @notice Decodes the given byte array into the original uninstallation parameters + function decodeUninstallationParams( + bytes memory _data + ) public pure returns (address pluginUpgrader) { + (pluginUpgrader) = abi.decode(_data, (address)); + } } diff --git a/packages/contracts/test/integration-testing/governance-plugins-setup.ts b/packages/contracts/test/integration-testing/governance-plugins-setup.ts index a69436e..d0d1ccc 100644 --- a/packages/contracts/test/integration-testing/governance-plugins-setup.ts +++ b/packages/contracts/test/integration-testing/governance-plugins-setup.ts @@ -119,18 +119,11 @@ describe("GovernancePluginsSetup processing", function () { const minMemberAccessProposalDuration = 60 * 60 * 24; // Install build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - GovernancePluginsSetupParams.METADATA.build.pluginSetup - .prepareInstallation - .inputs, - ), - [ - settings, - [alice.address], - minMemberAccessProposalDuration, - pluginUpgrader, - ], + const data = await setup.encodeInstallationParams( + settings, + [alice.address], + minMemberAccessProposalDuration, + pluginUpgrader, ); const installation = await installPlugin(psp, dao, pluginSetupRef, data); @@ -158,14 +151,7 @@ describe("GovernancePluginsSetup processing", function () { expect(await memberAccessPlugin.dao()).to.be.eq(dao.address); // Uninstall build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - GovernancePluginsSetupParams.METADATA.build.pluginSetup - .prepareUninstallation - .inputs, - ), - [pluginUpgrader], - ); + const data = await setup.encodeUninstallationParams(pluginUpgrader); await uninstallPlugin( psp, dao, diff --git a/packages/contracts/test/integration-testing/personal-space-admin-setup.ts b/packages/contracts/test/integration-testing/personal-space-admin-setup.ts index 01d907b..24300ee 100644 --- a/packages/contracts/test/integration-testing/personal-space-admin-setup.ts +++ b/packages/contracts/test/integration-testing/personal-space-admin-setup.ts @@ -22,7 +22,6 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { BigNumber } from "ethers"; import { ethers } from "hardhat"; -import { toHex } from "../../utils/ipfs"; describe("PersonalSpaceAdmin processing", function () { let alice: SignerWithAddress; @@ -88,6 +87,12 @@ describe("PersonalSpaceAdmin processing", function () { before(async () => { const release = 1; + // Deploy setup. + setup = PersonalSpaceAdminPluginSetup__factory.connect( + (await pluginRepo["getLatestVersion(uint8)"](release)).pluginSetup, + alice, + ); + pluginSetupRef = { versionTag: { release: BigNumber.from(release), @@ -101,14 +106,7 @@ describe("PersonalSpaceAdmin processing", function () { const initialEditor = alice.address; // Install build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - PersonalSpaceAdminPluginSetupParams.METADATA.build.pluginSetup - .prepareInstallation - .inputs, - ), - [initialEditor], - ); + const data = await setup.encodeInstallationParams(initialEditor); const results = await installPlugin(psp, dao, pluginSetupRef, data); plugin = PersonalSpaceAdminPlugin__factory.connect( @@ -121,14 +119,7 @@ describe("PersonalSpaceAdmin processing", function () { expect(await plugin.dao()).to.be.eq(dao.address); // Uninstall build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - PersonalSpaceAdminPluginSetupParams.METADATA.build.pluginSetup - .prepareUninstallation - .inputs, - ), - [], - ); + const data = "0x"; // no parameters await uninstallPlugin(psp, dao, plugin, pluginSetupRef, data, []); }); }); diff --git a/packages/contracts/test/integration-testing/space-setup.ts b/packages/contracts/test/integration-testing/space-setup.ts index 734f575..00cfa21 100644 --- a/packages/contracts/test/integration-testing/space-setup.ts +++ b/packages/contracts/test/integration-testing/space-setup.ts @@ -107,13 +107,10 @@ describe("SpacePluginSetup processing", function () { beforeEach(async () => { // Install build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - SpacePluginSetupParams.METADATA.build.pluginSetup - .prepareInstallation - .inputs, - ), - [toHex("ipfs://1234"), ADDRESS_ZERO, pluginUpgrader], + const data = await setup.encodeInstallationParams( + toHex("ipfs://1234"), + ADDRESS_ZERO, + pluginUpgrader, ); const results = await installPlugin(psp, dao, pluginSetupRef, data); @@ -130,14 +127,7 @@ describe("SpacePluginSetup processing", function () { expect(await plugin.dao()).to.be.eq(dao.address); // Uninstall build 1. - const data = ethers.utils.defaultAbiCoder.encode( - getNamedTypesFromMetadata( - SpacePluginSetupParams.METADATA.build.pluginSetup - .prepareUninstallation - .inputs, - ), - [pluginUpgrader], - ); + const data = await setup.encodeUninstallationParams(pluginUpgrader); await uninstallPlugin(psp, dao, plugin, pluginSetupRef, data, []); }); });