Vulnerability: Kicked oDAO members' votes taken into account  Acknowledged
Severity: medium

Description:
oDAO members can vote on proposals or submit external data to the system, acting as an oracle. Data submission is based on a vote by itself, and multiple oDAO members must submit the same data until a configurable threshold (51% by default) is reached for the data to be confirmed.\\nWhen a member gets kicked or leaves the oDAO after voting, their vote is still accounted for while the total number of oDAO members decreases.\\nA (group of) malicious oDAO actors may exploit this fact to artificially lower the consensus threshold by voting for a proposal and then leaving the oDAO. This will leave excess votes with the proposal while the total member count decreases.\\nFor example, let's assume there are 17 oDAO members. 9 members must vote for the proposal for it to pass (52.9%). Let's assume 8 members voted for, and the rest abstained and is against the proposal (47%, threshold not met). The proposal is unlikely to pass unless two malicious oDAO members leave the DAO, lowering the member count to 15 in an attempt to manipulate the vote, suddenly inflating vote power from 8/17 (47%; rejected) to 8/15 (53.3%; passed).\\nThe crux is that the votes of ex-oDAO members still count, while the quorum is based on the current oDAO member number.\\nHere are some examples, however, this is a general pattern used for oDAO votes in the system.\\nExample: RocketNetworkPrices\\nMembers submit votes via `submitPrices()`. If the threshold is reached, the proposal is executed. Quorum is based on the current oDAO member count, votes of ex-oDAO members are still accounted for. If a proposal is a near miss, malicious actors can force execute it by leaving the oDAO, lowering the threshold, and then calling `executeUpdatePrices()` to execute it.\\n```\\nRocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));\\nif (calcBase.mul(submissionCount).div(rocketDAONodeTrusted.getMemberCount()) >= rocketDAOProtocolSettingsNetwork.getNodeConsensusThreshold()) {\\n // Update the price\\n updatePrices(\\_block, \\_rplPrice);\\n}\\n```\\n\\n```\\nfunction executeUpdatePrices(uint256 \\_block, uint256 \\_rplPrice) override external onlyLatestContract("rocketNetworkPrices", address(this)) {\\n // Check settings\\n```\\n\\nRocketMinipoolBondReducer\\nThe `RocketMinipoolBondReducer` contract's `voteCancelReduction` function takes old votes of previously kicked oDAO members into account. This results in the vote being significantly higher and increases the potential for malicious actors, even after their removal, to sway the vote. Note that a canceled bond reduction cannot be undone.\\n```\\nRocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));\\nuint256 quorum = rocketDAONode.getMemberCount().mul(rocketDAONodeTrustedSettingsMinipool.getCancelBondReductionQuorum()).div(calcBase);\\nbytes32 totalCancelVotesKey = keccak256(abi.encodePacked("minipool.bond.reduction.vote.count", \\_minipoolAddress));\\nuint256 totalCancelVotes = getUint(totalCancelVotesKey).add(1);\\nif (totalCancelVotes > quorum) {\\n```\\n\\nRocketNetworkPenalties\\n```\\nRocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));\\nif (calcBase.mul(submissionCount).div(rocketDAONodeTrusted.getMemberCount()) >= rocketDAOProtocolSettingsNetwork.getNodePenaltyThreshold()) {\\n setBool(executedKey, true);\\n incrementMinipoolPenaltyCount(\\_minipoolAddress);\\n}\\n```\\n\\n```\\n// Executes incrementMinipoolPenaltyCount if consensus threshold is reached\\nfunction executeUpdatePenalty(address \\_minipoolAddress, uint256 \\_block) override external onlyLatestContract("rocketNetworkPenalties", address(this)) {\\n // Get contracts\\n RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));\\n // Get submission keys\\n```\\n

Impact:

Recommended mitigation:
Track oDAO members' votes and remove them from the tally when the removal from the oDAO is executed.