# Revoking vesting schedule does not subtract user votes correctly

ZivoeVestingRewards.revokeVestingSchedule subtracts only the withdrawable amount from vote checkpoints, leaving revoked users with inflated governance voting power.

- Payout: Contest reward
- Severity: high
- Program: Zivoe
- Credited: 0xAnmol
- Disclosed: 2024-03-19
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-03-zivoe-judging/issues/118
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AH-4
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:governance

**Target:** ZivoeRewardsVesting vesting schedule revocation / vote checkpoints
**Root cause:** revokeVestingSchedule decreases the account checkpoint only by amountWithdrawable(account) instead of the full remaining vested amount (vestingAmount - totalWithdrawn + amount), so revoked voting power persists.
**Steps:**
1. Create vesting schedule for moe of 6000 ether with cliff 0, duration 360, revocable true via `try_createVestingSchedule`.
2. Roll block forward; confirm `getPastVotes(moe)` == 6000 ether.
3. Call `try_revokeVestingSchedule(vestZVE, moe)`; balanceOf(moe) becomes 0.
4. Roll block forward; `getPastVotes(moe)` still returns 6000 ether — votes never subtracted.
5. Frontrun revoke by withdrawing entitled tokens so amountWithdrawable is ~0, maximizing retained votes.
**How found:** Code reading of revokeVestingSchedule: noticed the checkpoint subtraction uses `amount = amountWithdrawable(account)` rather than the revoked/remaining vesting amount, and reasoned that withdrawable is often near zero (frontrun withdrawal or early revocation).
**Exploitation:** A user with a revocable vesting schedule withdraws vested tokens then lets the schedule be revoked; since checkpoint subtraction uses only the (near-zero) withdrawable amount, the user retains full voting power and can vote on governance proposals despite having no tokens.
**Insight:** When auditing vote/checkpoint accounting, verify every state-changing path that removes tokens also subtracts the full removed quantity from both account and totalSupply checkpoints — revoke/burn paths commonly reuse a 'withdrawable' variable that understates the delta.
