# Vote dedup and snapshot weight errors

Votes counted twice or weighted from current state instead of the historical snapshot

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2025-07-03. Updated 2026-11-01._

## How it works
Vote tallying assumes two things that code often fails to enforce: that each voter contributes once, and that weight reflects the voter's entitlement at the snapshot time. When either assumption breaks, a minority share can cross a threshold, or a voter gains weight they never held. The root cause is a mismatch between the accounting the code performs and the invariant governance depends on: dedup keyed on (proposal, voter), and weight reconstructed from historical state.

## Where it shows up
- Vote-accumulating functions (vote, veto, propose) with no `hasVoted`/per-user mapping keyed on proposal and voter [E3](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-08.md)
- View functions that take a historical timestamp but read current storage flags (e.g. `isSMNFT`, `locked[tId]`) [E2](https://bugbountylibrary.com/r/c4%3A2025-05-blackhole%3AM-20.md)
- Sentinel values like `address(0)` used for both "unset" and "self-delegated", with guards checking `== address(0)` [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01.md)
- Contribution or delegation paths where a third party can set another user's delegate
- Balance/weight queries that loop over tokens filtering on mutable current state

## How to review
For every function that adds voting power, confirm a per-(proposal, voter) record is written and checked before accumulation. For every historical query, confirm each storage read is either immutable or reconstructed as of the queried timestamp; flag any current-state flag mixed with a past timestamp. For delegation, confirm the sentinel for "self" is distinguishable from "unset", so a guard on `address(0)` cannot be triggered by a deliberate self-delegation. The invariant: tally equals the sum over distinct voters of their snapshot-time entitlement, no more.

## Variants seen
- Missing dedup in veto: same address repeats to reach threshold [E3](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-08.md)
- Historical query reads current flag, inflating past weight [E2](https://bugbountylibrary.com/r/c4%3A2025-05-blackhole%3AM-20.md)
- Sentinel collision lets third party overwrite self-delegation [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01.md)

## Impact and severity
Minority holders can veto or pass proposals beyond entitlement, and voting power can be hijacked without the victim's knowledge [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01.md)[E3](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-08.md). Severity rises where thresholds gate fund movement or proposal outcomes; silent hijack [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01.md) is worse because the victim sees no action.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-01.md
- E2: https://bugbountylibrary.com/r/c4%3A2025-05-blackhole%3AM-20.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-08.md
