# Delegators can Avoid Lock Commitments if they can Reliably get Themselves Blocked when Needed

Delegator locks tokens briefly, delegates to a long-locked account for max voting power, then gets blocked to force-undelegate and withdraw early.

- Payout: Contest reward
- Severity: high
- Program: FIAT DAO
- Credited: Respx
- Disclosed: 2022-10-03
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-08-fiatdao-findings/issues/204
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-fiatdao%3AH-02
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:business-logic vuln:governance

**Target:** VotingEscrow / Blocklist smart contracts (Solidity)
**Root cause:** forceUndelegate() resets the delegator's lock end to its own short/expired lock rather than the delegatee's long lock end, so a blocked delegator can withdraw immediately despite having delegated votes to a 52-week lock.
**Steps:**
1. Rider (contract, 100k tokens) locks for 1 week; Horse (1 token) locks for 52 weeks.
2. Rider calls `delegate(Horse)`; Horse gains maximized voting power and can extend its lock.
3. When Rider wants tokens back, get Rider blocklisted: `Blocklist.block(RiderAddress)` calls `ve.forceUndelegate(RiderAddress)`.
4. Rider is now undelegated with an expired lock; call `ve.withdraw()` to recover tokens.
5. Repeat with a fresh Rider account.
**How found:** Code reading of forceUndelegate/withdraw in VotingEscrow.sol; noticed forceUndelegate resets lock end to the delegator's own endpoint rather than the delegatee's, and reasoned that blocklisting (an external, assumed-available action) could be weaponized to escape lock commitments.
**Exploitation:** User splits tokens across two accounts: a short-lock delegator contract and a long-lock delegatee. Delegation transfers voting power to the long lock while the delegator retains withdrawal rights. Triggering blocklist on the delegator calls forceUndelegate, which sets the delegator's lock end to its own (short) endpoint, allowing immediate withdraw() and recycling of tokens into a new account.
**Escalation:** Repeatable loop with fresh accounts lets the user perpetually enjoy max voting power without committing tokens, breaking protocol incentives.
**Insight:** When a privileged path (blocklist/forceUndelegate) mutates lock or delegation state, check whether it preserves the invariant that a delegator's lock end >= delegatee's lock end; any reset to the delegator's own shorter endpoint is an escape hatch.
