fix(RankedBallot): Validate candidate ID bounds and uniqueness in vote()#245
Conversation
RankedBallot.vote() had two security gaps: 1. No bounds check -- voteArr[i] >= totalCandidates caused an unguarded out-of-bounds array access (panic revert, no custom error) 2. No uniqueness check -- submitting [0,0,0] let a single candidate accumulate all rank-weighted points, corrupting election results Fix: add a bool[] memory seen array to track processed IDs and revert with new typed errors InvalidCandidateID and DuplicateCandidateID. Also adds both new errors to Errors.sol and ErrorMessage.ts. Closes AOSSIE-Org#244 Closes AOSSIE-Org#228
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Fixes two silent security vulnerabilities in
RankedBallot.vote()that could corrupt election results.Closes #244
Closes #228
Problem
Bug 1 — No bounds check on candidate IDs
If a voter submitted a
voteArrcontaining a value>= totalCandidates, the contract would attempt to write tocandidateVotes[voteArr[i]]out-of-bounds, causing an unguarded Solidity panic (array-out-of-bounds revert) with no descriptive error. Malformed input was not rejected cleanly.Bug 2 — No uniqueness check (vote manipulation)
A voter could submit a ranking like
[0, 0, 0]— the same candidate ID repeated across all positions. Since no uniqueness validation existed, the candidate at index0would receive points for every rank (n + (n-1) + (n-2) + ...), while all other candidates received zero. This silently corrupted results without any revert.Fix
Added a
bool[] memory seentracking array invote():Two new typed errors added to
Errors.sol:Both errors also registered in
client/app/helpers/ErrorMessage.tsper contributing guidelines.Files Changed
blockchain/contracts/ballots/RankedBallot.solvote()blockchain/contracts/ballots/interface/Errors.solInvalidCandidateID,DuplicateCandidateIDclient/app/helpers/ErrorMessage.tsChecklist
Errors.solinterface patternErrorMessage.tsupdated per contributing guidelinesupstream/main