From e48a6edf1b6275175eb2e20f11968039d5365cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Tue, 14 Jan 2025 15:32:02 +0100 Subject: [PATCH] Proposal creation and voting steps for LockToVote --- src/LockToVotePlugin.sol | 82 +++++++++++++++++++++++++++------- src/interfaces/ILockToVote.sol | 9 ++-- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/src/LockToVotePlugin.sol b/src/LockToVotePlugin.sol index b4d4203..6e53083 100644 --- a/src/LockToVotePlugin.sol +++ b/src/LockToVotePlugin.sol @@ -245,21 +245,64 @@ contract LockToVotePlugin is uint256 _proposalId, address _voter, VoteOption _voteOption, - uint256 _newVotingPower + uint256 _votingPower ) external auth(LOCK_MANAGER_PERMISSION_ID) { ProposalVoting storage proposal_ = proposals[_proposalId]; - if (!_canVote(proposal_, _voter, _newVotingPower)) { + if (!_canVote(proposal_, _voter, _votingPower)) { revert VoteCastForbidden(_proposalId, _voter); + } else if (_voteOption == VoteOption.None) { + revert VotingNoneForbidden(_proposalId, _voter); + } else if (_votingPower < proposal_.votes[_voter].votingPower) { + revert LowerBalanceForbidden(); } - // Add the difference between the new voting power and the current one + // Same vote + if (_voteOption == proposal_.votes[_voter].voteOption) { + // Same balance, nothing to do + if (_votingPower == proposal_.votes[_voter].votingPower) return; + + // More balance + uint256 diff = _votingPower - proposal_.votes[_voter].votingPower; + proposal_.votes[_voter].votingPower = _votingPower; + + if (proposal_.votes[_voter].voteOption == VoteOption.Yes) { + proposal_.tally.yes += diff; + } else if (proposal_.votes[_voter].voteOption == VoteOption.No) { + proposal_.tally.no += diff; + } else { + proposal_.tally.abstain += diff; + } + } else { + // Was there a vote? + if (proposal_.votes[_voter].votingPower > 0) { + // Undo that vote + if (proposal_.votes[_voter].voteOption == VoteOption.Yes) { + proposal_.tally.yes -= proposal_.votes[_voter].votingPower; + } else if ( + proposal_.votes[_voter].voteOption == VoteOption.No + ) { + proposal_.tally.no -= proposal_.votes[_voter].votingPower; + } else { + proposal_.tally.abstain -= proposal_ + .votes[_voter] + .votingPower; + } + } - uint256 diff = _newVotingPower - proposal_.votes[_voter].votingPower; - proposal_.approvalTally += diff; - proposal_.votes[_voter] += diff; + // Register the new vote + if (_voteOption == VoteOption.Yes) { + proposal_.tally.yes += _votingPower; + } else if (_voteOption == VoteOption.No) { + proposal_.tally.no += _votingPower; + } else { + proposal_.tally.abstain += _votingPower; + } + proposal_.votes[_voter].voteOption = _voteOption; + proposal_.votes[_voter].votingPower = _votingPower; + } - emit VoteCast(_proposalId, _voter, _voteOption, _newVotingPower); + emit VoteCast(_proposalId, _voter, _voteOption, _votingPower); _checkEarlyExecution(_proposalId, proposal_, _voter); } @@ -271,22 +314,31 @@ contract LockToVotePlugin is ) external auth(LOCK_MANAGER_PERMISSION_ID) { ProposalVoting storage proposal_ = proposals[_proposalId]; - if (proposal_.votes[_voter] == 0 || !_isProposalOpen(proposal_)) + if ( + proposal_.votes[_voter].votingPower == 0 || + !_isProposalOpen(proposal_) + ) { + // Nothing to do return; + } - // Subtract the old votes from the global tally - proposal_.approvalTally -= proposal_.votes[_voter]; - - // Clear the voting power - proposal_.votes[_voter] = 0; + // Undo that vote + if (proposal_.votes[_voter].voteOption == VoteOption.Yes) { + proposal_.tally.yes -= proposal_.votes[_voter].votingPower; + } else if (proposal_.votes[_voter].voteOption == VoteOption.No) { + proposal_.tally.no -= proposal_.votes[_voter].votingPower; + } else { + proposal_.tally.abstain -= proposal_.votes[_voter].votingPower; + } + proposal_.votes[_voter].votingPower = 0; emit VoteCleared(_proposalId, _voter); } /// @inheritdoc ILockToVote function usedVotingPower( - uint256 proposalId, - address voter + uint256 _proposalId, + address _voter ) public view returns (uint256) { return proposals[proposalId].approvals[voter]; } diff --git a/src/interfaces/ILockToVote.sol b/src/interfaces/ILockToVote.sol index c31d80b..37d184f 100644 --- a/src/interfaces/ILockToVote.sol +++ b/src/interfaces/ILockToVote.sol @@ -90,13 +90,13 @@ interface ILockToVote is ILockToVoteBase { /// @param proposalId The ID of the proposal to vote on. /// @param voter The address of the account whose vote will be registered /// @param voteOption The value of the new vote to register. If an existing vote existed, it will be replaced. - /// @param newVotingPower The new balance that should be allocated to the voter. It can only be bigger. - /// @dev newVotingPower updates any prior voting power, it does not add to the existing amount. + /// @param votingPower The new balance that should be allocated to the voter. It can only be bigger. + /// @dev votingPower updates any prior voting power, it does not add to the existing amount. function vote( uint256 proposalId, address voter, VoteOption voteOption, - uint256 newVotingPower + uint256 votingPower ) external; /// @notice Reverts the existing voter's vote, if any. @@ -114,9 +114,10 @@ interface ILockToVote is ILockToVoteBase { uint256 proposalId, address voter, VoteOption voteOption, - uint256 newVotingPower + uint256 votingPower ); event VoteCleared(uint256 proposalId, address voter); error VoteCastForbidden(uint256 proposalId, address voter); error VotingNoneForbidden(uint256 proposalId, address voter); + error LowerBalanceForbidden(); }