requiredQuorum may be lower than the actual value, it is possible that the vote will pass early.
Proof of Concept
A canFinalizeBallot is used to determine whether a quorum is present.
function canFinalizeBallot( uint256 ballotID ) external view returns (bool)
{
Ballot memory ballot = ballots[ballotID];
if ( ! ballot.ballotIsLive )
return false;
// Check that the minimum duration has passed
if (block.timestamp < ballot.ballotMinimumEndTime )
return false;
// Check that the required quorum has been reached
if ( totalVotesCastForBallot(ballotID) < requiredQuorumForBallotType( ballot.ballotType ))
return false;
return true;
}
requiredQuorumForBallotType through salt token to calculate the total supply minimumQuorum:
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L334
Vulnerability details
Impact
requiredQuorum
may be lower than the actual value, it is possible that the vote will pass early.Proof of Concept
A canFinalizeBallot is used to determine whether a quorum is present.
requiredQuorumForBallotType
through salt token to calculate the total supplyminimumQuorum
:The problem is that
totalSupply
is not a fixed value, andminimumQuorum
is lower than the actual value whentotalSupply
decreases:Tools Used
vscode, manual
Recommended Mitigation Steps
Use the snapshot feature when voting, such as using openzeppelin's governance library.
Assessed type
Governance