Platform: Code4rena
Start Date: 03/08/2023
Pot Size: $90,500 USDC
Total HM: 6
Participants: 36
Period: 7 days
Judge: 0xean
Total Solo HM: 1
Id: 273
League: ETH
Rank: 32/36
Findings: 1
Award: $36.16
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MiloTruck
Also found by: 0xbepresent, 0xnev, 0xprinc, HE1M, Mirror, Sathish9098, Udsen, arialblack14, berlin-101, eierina, hals, ktg, nobody2018
36.1616 USDC - $36.16
In the SecurityCouncilNomineeElectionGovernorCountingUpgradeable:_countVote() there is not any validation that the contenders can vote to themselves.
Additionally the nominees can vote to themselves since there is not any restriction in the SecurityCouncilMemberElectionGovernorCountingUpgradeable._countVote() function.
Add a restriction that contender or nominee can not vote to themselves.
The SecurityCouncilNomineeElectionGovernorCountingUpgradeable::_countVote() allows the users to count the votes for multiple contenders
in order to nominee them.
The next code block helps to calculate the actualVotes
variable which is the exact number that helps the contenteder to be a nominee
, therefore the voter's votes are not wasted and it is only used the necessary amount:
File: SecurityCouncilNomineeElectionGovernorCountingUpgradeable.sol 093: 094: uint256 prevVotesReceived = election.votesReceived[contender]; 095: uint256 votesThreshold = quorum(proposalSnapshot(proposalId)); 096: 097: uint256 actualVotes = votes; 098: if (prevVotesReceived + votes >= votesThreshold) { 099: // we pushed the contender over the line 100: // we should only give the contender enough votes to get to the line so that we don't waste votes 101: actualVotes = votesThreshold - prevVotesReceived; 102: 103: // push the contender to the nominees 104: _addNominee(proposalId, contender); 105: } 106: 107: election.votesUsed[account] = prevVotesUsed + actualVotes; 108: election.votesReceived[contender] = prevVotesReceived + actualVotes;
The problem is in the next code block helps to ensure the voter has enough avaliabale vote weight. Since not all the voter's votes will be used, it is not necessary to validates all the votes
number:
File: SecurityCouncilNomineeElectionGovernorCountingUpgradeable.sol 87: NomineeElectionCountingInfo storage election = _elections[proposalId]; 88: uint256 prevVotesUsed = election.votesUsed[account]; 89: 90: if (votes + prevVotesUsed > weight) { 91: revert InsufficientTokens(votes, prevVotesUsed, weight); 92: }
Consider validates only the votes that will be necessary to cover the contender threshold.
-- if (votes + prevVotesUsed > weight) { ++ if (actualVotes + prevVotesUsed > weight) { revert InsufficientTokens(votes, prevVotesUsed, weight); }
relay()
functions don't have the payable
modifierThe SecurityCouncilMemberElectionGovernor.relay() and SecurityCouncilNomineeElectionGovernor.relay() functions don't have the payable
modifier.
The requirements of the AddressUpgradeable.functionCallWithValue() are:
value
.payable
.Consider adding the payable
modifier in the relay()
functions.
#0 - c4-judge
2023-08-18T23:27:45Z
0xean marked the issue as grade-c
#1 - c4-judge
2023-08-18T23:59:21Z
0xean marked the issue as grade-b