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: 16/36
Findings: 2
Award: $437.06
🌟 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
351.9498 USDC - $351.95
When adding a security council only chain id and security council address are checked to detect whether adding the council is allowed: https://github.com/arbitrumfoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/SecurityCouncilManager.sol#L255-L256
When removing a security council also the address of the update action is checked to make the match: https://github.com/arbitrumfoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/SecurityCouncilManager.sol#L255-L256.
This can mean two things.
When in discussion with the team the question whether this is explicitly documented as a reference for implementation could not be clarified.
I am not sure if that is intended but this line favors later entries in the nominees array passed to the function as the index is added to the weight: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/modules/SecurityCouncilMemberElectionGovernorCountingUpgradeable.sol#L206
The "excludeNominee" function of "SecurityCouncilNomineeElectionGovernor.sol" enforces that it can only be called during the vetting period via the "onlyVettingPeriod" modifier: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilNomineeElectionGovernor.sol#L269.
However, the "inludeNominee" function does not enforce it as there is no option to extend the vetting period implemented: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilNomineeElectionGovernor.sol#L290. So no additional nominees could be added to achieve the candidates after the vetting period ended. This may be implemented as expected.
But if the vetter makes a mistake after the vetting period ended, no nominee added through failure could be removed and the added candidate could be voted for. It is unclear if this is intended. If so, the vetter must be trusted to not make mistakes.
The createActionRouteDataWithDefaults() function within UpgradeExecRouteBuilder.sol (https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/UpgradeExecRouteBuilder.sol#L186) is only used in tests. It should be removed from the contract and moved into the test folder.
This becomes apparent for example here: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/gov-action-contracts/AIPs/SecurityCouncilMgmt/GovernanceChainSCMgmtActivationAction.sol#L69. "TIMELOCK_PROPOSER_ROLE" should be used instead. For "TIMELOCK_CANCELLER_ROLE" this is done consistently: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/gov-action-contracts/AIPs/SecurityCouncilMgmt/GovernanceChainSCMgmtActivationAction.sol#L70.
Suggested implementation:
function _removeMemberFromCohortArray(address _member) internal returns (Cohort) { for (uint256 i = 0; i <= Cohort.SECOND; i++) { address[] storage cohort = i == Cohort.FIRST ? firstCohort : secondCohort; for (uint256 j = 0; j < cohort.length; j++) { if (_member == cohort[j]) { cohort[j] = cohort[cohort.length - 1]; cohort.pop(); return Cohort(i); } } } revert NotAMember(_member); }
Safe2 parameter does not use underscore: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/gov-action-contracts/AIPs/SecurityCouncilMgmt/SecurityCouncilMgmtUpgradeLib.sol#L30-L32C35
Example: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/factories/L2SecurityCouncilMgmtFactory.sol#L141. This should be harmonized. The suggestion is to use "remover".
Several examples of this can be found in SecurityCouncilManager.sol: https://github.com/ArbitrumFoundation/governance/blob/security-council-mgmt--base/src/security-council-mgmt/SecurityCouncilManager.sol#L113, https://github.com/ArbitrumFoundation/governance/blob/security-council-mgmt--base/src/security-council-mgmt/SecurityCouncilManager.sol#L149, https://github.com/ArbitrumFoundation/governance/blob/security-council-mgmt--base/src/security-council-mgmt/SecurityCouncilManager.sol#L172, https://github.com/ArbitrumFoundation/governance/blob/security-council-mgmt--base/src/security-council-mgmt/SecurityCouncilManager.sol#L319,
There is a mix of using VoteType and integers to indicate the "support" of votes. For example here the VoteType enum is used: https://github.com/ArbitrumFoundation/governance/blob/security-council-mgmt--base/src/security-council-mgmt/governors/SecurityCouncilMemberRemovalGovernor.sol#L170. Here an integer is used: https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/modules/SecurityCouncilMemberElectionGovernorCountingUpgradeable.sol#L102. Using the enum consistently is preferable.
Via the "excludeNominee" function in SecurityCouncilNomineeElectionGovernor.sol a nominee can be excluded by a vetter.
But because this function blacklists the nominee's address via "election.isExcluded[nominee] = true;" (https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilNomineeElectionGovernor.sol#L279) the vetter cannot revert this by using the "includeNominee" function as it does not reset this entry (https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilNomineeElectionGovernor.sol#L290).
If the implementation should be robust to cover for vetter mistakes, resetting the "election.isExcluded" state of the nominee address (and decreasing the election.excludedNomineeCount) should be implemented within the "includeNominee" function.
For "totalUsedVotes" the following is used:
totalUsedVotes: prevVotesUsed + votes
For "weightReceived" the following is used:
weightReceived: election.weightReceived[nominee]
which could have been the following to be consistent:
weightReceived: prevWeightReceived + weight
#0 - 0xSorryNotSorry
2023-08-14T13:24:31Z
L-02 is dup of #108 L-12 is dup of #67
#1 - c4-judge
2023-08-18T23:31:14Z
0xean marked the issue as grade-a
🌟 Selected for report: catellatech
Also found by: 0xSmartContract, 0xnev, K42, MSK, Sathish9098, berlin-101, hals, kodyvim, yixxas
50 hours
#0 - c4-judge
2023-08-18T23:48:07Z
0xean marked the issue as grade-b