diff --git a/packages/contracts/src/governance/MainVotingPlugin.sol b/packages/contracts/src/governance/MainVotingPlugin.sol index 8f30dac..83d26aa 100644 --- a/packages/contracts/src/governance/MainVotingPlugin.sol +++ b/packages/contracts/src/governance/MainVotingPlugin.sol @@ -18,10 +18,12 @@ bytes4 constant MAIN_SPACE_VOTING_INTERFACE_ID = MainVotingPlugin.initialize.sel MainVotingPlugin.proposeEdits.selector ^ MainVotingPlugin.proposeAcceptSubspace.selector ^ MainVotingPlugin.proposeRemoveSubspace.selector ^ + MainVotingPlugin.proposeRemoveMember.selector ^ MainVotingPlugin.addEditor.selector ^ MainVotingPlugin.removeEditor.selector ^ MainVotingPlugin.addMember.selector ^ MainVotingPlugin.removeMember.selector ^ + MainVotingPlugin.leaveSpace.selector ^ MainVotingPlugin.cancelProposal.selector; /// @title MainVotingPlugin (Address list) @@ -147,19 +149,23 @@ contract MainVotingPlugin is Addresslist, MajorityVotingBase, IEditors, IMembers emit MemberRemoved(address(dao()), _account); } - /// @notice Removes + /// @notice Removes msg.sender from the list of editors. If the last editors leaves the space, the space will become read only. function leaveSpace() public { - if (!isEditor(msg.sender)) { - revert NotAnEditor(); - } - // Not checking whether msg.sender is the last editor. It is acceptable - // that a DAO/Space remains in read-only mode, as it can always be forked. + if (isEditor(msg.sender)) { + // Not checking whether msg.sender is the last editor. It is acceptable + // that a DAO/Space remains in read-only mode, as it can always be forked. - address[] memory _editors = new address[](1); - _editors[0] = msg.sender; + address[] memory _editors = new address[](1); + _editors[0] = msg.sender; - _removeAddresses(_editors); - emit EditorLeft(address(dao()), msg.sender); + _removeAddresses(_editors); + emit EditorLeft(address(dao()), msg.sender); + } + + if (members[msg.sender]) { + members[msg.sender] = false; + emit MemberLeft(address(dao()), msg.sender); + } } /// @notice Returns whether the given address is currently listed as an editor diff --git a/packages/contracts/src/governance/MemberAccessPlugin.sol b/packages/contracts/src/governance/MemberAccessPlugin.sol index 4acd151..5db8c18 100644 --- a/packages/contracts/src/governance/MemberAccessPlugin.sol +++ b/packages/contracts/src/governance/MemberAccessPlugin.sol @@ -124,11 +124,6 @@ contract MemberAccessPlugin is IMultisig, PluginUUPSUpgradeable, ProposalUpgrade /// @param mainVotingPlugin The address of the main voting plugin for the space. Used to apply permissions for it. event MultisigSettingsUpdated(uint64 proposalDuration, address mainVotingPlugin); - /// @notice Emitted when a member leaves the space. - /// @param dao The address of the DAO whose plugin has removed a member. - /// @param member The address of the existing member being removed. - event MemberLeft(address dao, address member); - /// @notice Initializes Release 1, Build 1. /// @dev This method is required to support [ERC-1822](https://eips.ethereum.org/EIPS/eip-1822). /// @param _dao The IDAO interface of the associated DAO. @@ -248,45 +243,6 @@ contract MemberAccessPlugin is IMultisig, PluginUUPSUpgradeable, ProposalUpgrade return createProposal(_metadata, _actions); } - /// @notice Creates and executes a proposal that makes the DAO revoke membership permission from the sender address. - /// @param _metadata The metadata of the proposal. - function leaveSpace(bytes calldata _metadata) external { - if (!isMember(msg.sender)) { - revert AlreadyNotMember(msg.sender); - } - - // Build the list of actions - IDAO.Action[] memory _actions = new IDAO.Action[](1); - _actions[0] = IDAO.Action({ - to: address(multisigSettings.mainVotingPlugin), - value: 0, - data: abi.encodeCall(MainVotingPlugin.removeMember, (msg.sender)) - }); - - uint _proposalId = _createProposalId(); - emit ProposalCreated({ - proposalId: _proposalId, - creator: msg.sender, - metadata: _metadata, - startDate: block.timestamp.toUint64(), - endDate: block.timestamp.toUint64(), - actions: _actions, - allowFailureMap: uint8(0) - }); - - // Register as a proposal - Proposal storage proposal_ = proposals[_proposalId]; - - proposal_.parameters.snapshotBlock = uint64(block.number) - 1; - proposal_.parameters.startDate = block.timestamp.toUint64(); - proposal_.parameters.endDate = block.timestamp.toUint64(); - proposal_.actions.push(_actions[0]); - - _executeProposal(dao(), _createProposalId(), proposals[_proposalId].actions, 0); - - emit MemberLeft(address(dao()), msg.sender); - } - /// @inheritdoc IMultisig /// @dev The second parameter is left empty to keep compatibility with the existing multisig interface function approve(uint256 _proposalId) public {