In castVote, the contract calls:
This fetches the current veRAAC balance. However, typical governance models (e.g., Compound, Uniswap, Aave) utilize snapshot‐based voting to prevent users from acquiring or transferring voting power after a proposal is created. The present implementation:
Never records a user’s voting power at proposal creation or the start of voting.
Allows them to lock or increase tokens in veRAAC at any point before casting a vote.
Thus a user can drastically raise their veRAAC immediately before castVote, granting them more voting power than they held at proposal creation.
Proposal Creation
At time T0, a user with minimal veRAAC triggers or sees a proposal. No snapshot is stored.
Mid-Vote
The user (or a whale) decides near the end of the voting period to lock/increase tokens in the veRAAC contract, boosting their live voting power.
CastVote
Because castVote calls _veToken.getVotingPower(msg.sender) at the time of voting, they now have a large weight despite holding few or no tokens at T0.
Votes with Inflated Power
The system has no reference to a “frozen” or “past” block to confirm the user’s voting power at proposal creation. The inflated vote stands.
Vote Manipulation
A user or group can easily accumulate veRAAC tokens after a proposal is posted (or near its end), influencing the result far more than if their power were locked at creation.
Contradicts Typical Governance Assumptions
The doc states: “Users can lock RAAC tokens for voting power,” but standard governance often expects your power is fixed at the proposal’s start. Without a block-based snapshot, the system invites strategic last-minute locking that disrupts fair representation of users who held tokens early on.
Volatile & Over-Optimizable Governance
Because power is not snapshotted, the protocol is more vulnerable to immediate capital swings from outside sources who can buy or borrow RAAC, lock them for a short period, and cast votes with disproportionate influence.
A minimal demonstration in Foundry:
Because the contract calls getVotingPower without referencing a past block or snapshot, the user has full new power.
Implement Snapshot Voting:
A typical approach is to store each proposal’s start block in propose(...):
Then in castVote, use:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.