# require(winval > 0) can lead to votes never able to be finalized and locking users fund forever in certain situations

Vote created with voterPercent_=0 makes winVal always 0, so require(winVal>0) in _tryFinalize reverts forever, locking all staked funds.

- Payout: Contest reward
- Severity: medium
- Program: Goat
- Credited: Chad0
- Disclosed: 2024-06-12
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_goat_mar2024.pdf#3.2.12
- Library page: https://bugbountylibrary.com/r/cantina%3Agoat_mar2024%3A3.2.12
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:cantina sev:medium tech:solidity technique:source-review vuln:business-logic vuln:governance

**Target:** Voting.sol claimFor/_tryFinalize reward finalization
**Root cause:** LPercentage.validatePercent accepts 0, so vote.voterPercent can be 0; winVal is computed as a fraction of voterPercent, yielding 0 regardless of winner, and require(winVal > 0) in _tryFinalize always reverts.
**Steps:**
1. Create a vote via Voting with `voterPercent_ = 0`; validatePercent passes and vote.voterPercent is stored as 0.
2. Any user calls Controller.votingClaimFor() -> Voting.claimFor() -> Voting._tryFinalize().
3. winVal computes to 0 because voterPercent is 0, so `require(winVal > 0)` reverts.
4. Since _tryFinalize is only reachable via claimFor, the vote can never finalize and staked funds stay locked.
**How found:** Code reading of validatePercent bounds and the winVal computation path from claimFor into _tryFinalize, noticing 0 passes validation and propagates to the require.
**Exploitation:** Attacker opens a vote against a pool owner with voterPercent_=0, sacrificing only the 25% min attacker fund while locking the target's entire stake permanently; normal users misled by docs' 0% example self-lock funds.
**Escalation:** Repeatable against any pool owner at 25% cost ratio, enabling griefing/destruction of arbitrary pools.
**Insight:** When a validation helper accepts a boundary value (0), trace that value through downstream arithmetic into require() guards on finalization/withdrawal paths — zero multipliers silently brick state transitions.
