diff --git a/packages/contracts/src/governance/MainVotingPlugin.sol b/packages/contracts/src/governance/MainVotingPlugin.sol index 6aa37e9..861d161 100644 --- a/packages/contracts/src/governance/MainVotingPlugin.sol +++ b/packages/contracts/src/governance/MainVotingPlugin.sol @@ -417,6 +417,24 @@ contract MainVotingPlugin is Addresslist, MajorityVotingBase, IEditors, IMembers }); } + /// @notice Determines whether at least one editor besides the creator has approved + /// @param _proposalId The ID of the proposal to check. + function isMinParticipationReached(uint256 _proposalId) public view override returns (bool) { + Proposal storage proposal_ = proposals[_proposalId]; + + if (proposal_.tally.yes == 0 && proposal_.tally.no == 0 && proposal_.tally.abstain == 0) { + return false; + } + + // Just one voter + if (addresslistLengthAtBlock(proposal_.parameters.snapshotBlock) == 1) { + return true; + } + + // More voters expected + return proposal_.nonCreatorsVoted; + } + /// @inheritdoc MajorityVotingBase function _vote( uint256 _proposalId, @@ -455,6 +473,10 @@ contract MainVotingPlugin is Addresslist, MajorityVotingBase, IEditors, IMembers votingPower: 1 }); + if (proposalCreators[_proposalId] != msg.sender && !proposal_.nonCreatorsVoted) { + proposal_.nonCreatorsVoted = true; + } + if (_tryEarlyExecution && _canExecute(_proposalId)) { _execute(_proposalId); } @@ -512,5 +534,5 @@ contract MainVotingPlugin is Addresslist, MajorityVotingBase, IEditors, IMembers /// @dev This empty reserved space is put in place to allow future versions to add new /// variables without shifting down storage in the inheritance chain. /// https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - uint256[49] private __gap; + uint256[48] private __gap; } diff --git a/packages/contracts/src/governance/MemberAccessPlugin.sol b/packages/contracts/src/governance/MemberAccessPlugin.sol index 12e5cf2..df6d76c 100644 --- a/packages/contracts/src/governance/MemberAccessPlugin.sol +++ b/packages/contracts/src/governance/MemberAccessPlugin.sol @@ -157,9 +157,9 @@ contract MemberAccessPlugin is IMultisig, PluginUUPSUpgradeable, ProposalUpgrade _updateMultisigSettings(_multisigSettings); } - /// @notice Creates a new multisig proposal wrapped by proposeNewMember and proposeRemoveMember. + /// @notice Creates a new multisig proposal wrapped by proposeNewMember. /// @param _metadata The metadata of the proposal. - /// @param _actions A list of actions wrapped by proposeNewMember and proposeRemoveMember. + /// @param _actions A list of actions wrapped by proposeNewMember. /// @return proposalId The ID of the proposal. function createProposal( bytes calldata _metadata, diff --git a/packages/contracts/src/governance/base/MajorityVotingBase.sol b/packages/contracts/src/governance/base/MajorityVotingBase.sol index 49d6b93..323f3b6 100644 --- a/packages/contracts/src/governance/base/MajorityVotingBase.sol +++ b/packages/contracts/src/governance/base/MajorityVotingBase.sol @@ -130,6 +130,7 @@ abstract contract MajorityVotingBase is /// @param parameters The proposal parameters at the time of the proposal creation. /// @param tally The vote tally of the proposal. /// @param voters The votes casted by the voters. + /// @param nonCreatorsVoted Whether a wallet other than the creator voted on the proposal. /// @param actions The actions to be executed when the proposal passes. /// @param allowFailureMap A bitmap allowing the proposal to succeed, even if individual actions might revert. If the bit at index `i` is 1, the proposal succeeds even if the `i`th action reverts. A failure map value of 0 requires every action to not revert. struct Proposal { @@ -137,6 +138,7 @@ abstract contract MajorityVotingBase is ProposalParameters parameters; Tally tally; mapping(address => IMajorityVoting.VoteOption) voters; + bool nonCreatorsVoted; IDAO.Action[] actions; uint256 allowFailureMap; } @@ -573,5 +575,5 @@ abstract contract MajorityVotingBase is } /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)). - uint256[47] private __gap; + uint256[48] private __gap; }