# Delegation not revoked on withdrawal allows reward and voting power inflation post-maturity

AgentVeToken.withdraw() never clears delegation, so stake-then-withdraw cycles leave stale delegatee checkpoints that inflate uptime-based staker rewards in AgentRewardV3.

- Payout: Contest reward
- Severity: medium
- Program: Virtuals Protocol
- Credited: yaractf
- Disclosed: 2025-08-04
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-04-virtuals-protocol#m-20
- Library page: https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-20
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:governance vuln:reward-distribution

**Target:** AgentVeToken staking/veToken contract and AgentRewardV3 reward accounting
**Root cause:** withdraw() burns tokens and updates balance checkpoints but never calls _delegate(sender, address(0)), so the delegatee recorded at stake() time persists in delegation checkpoints after balance hits zero.
**Steps:**
1. Stake tokens via `stake(amount, receiver, delegatee)` on AgentVeToken, which calls `_delegate(receiver, delegatee)` and pushes a balance checkpoint.
2. Wait until `matureAt` so withdraw() is permitted.
3. Call `withdraw(amount)` for the full balance; tokens are burned and transferred back but delegation checkpoint for delegatee remains.
4. Repeat stake/withdraw cycles (even same block) to accumulate delegation history with zero net stake.
5. Observe `getClaimableStakerRewards` in AgentRewardV3 reading `veToken.getPastDelegates(account, reward.blockNumber)` and `dao.getPastScore(delegatee, ...)` to compute inflated uptime-based rewards.
**How found:** Code review of stake() vs withdraw() in AgentVeToken.sol: noticed stake() calls _delegate but withdraw() only burns and checkpoints balance, then traced getPastDelegates() usage in AgentRewardV3 reward math.
**Exploitation:** Attacker stakes and delegates to a chosen delegatee, withdraws at maturity, and repeats to seed historical delegation records while holding no stake; reward computation then credits uptime from the stale delegatee, inflating staker rewards and decoupling governance weight from actual stake.
**Insight:** When a staking contract checkpoints delegation and balance separately, verify every exit path (withdraw, burn, transfer-to-zero) clears delegation; reward formulas that read historical delegatee uptime are the payoff surface.
