# Inconsistent logic of increase unlock time to the expired locks

Expired VotingEscrow locks could be extended by delegating to another address, bypassing the 'Lock expired' check and restoring vote power.

- Payout: Contest reward
- Severity: medium
- Program: FIAT DAO
- Disclosed: 2022-10-03
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-08-fiatdao-findings/issues/254
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-fiatdao%3AM-03
- Tags: domain:web3 kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** VotingEscrow.sol increaseUnlockTime/delegate
**Root cause:** increaseUnlockTime only enforces the 'Lock expired' check when the lock is not delegated; the delegated branch skips the expiry check, so an expired lock can be extended after delegating.
**Steps:**
1. Alice creates a lock with end = now + WEEK
2. Advance time past WEEK so Alice's lock expires (balanceOf == 0)
3. `ve.connect(alice).increaseUnlockTime(lockTime)` reverts with 'Lock expired'
4. `ve.connect(alice).delegate(bob.address)` to move into the delegated branch
5. `ve.connect(alice).increaseUnlockTime(lockTime)` now succeeds
6. `ve.connect(alice).delegate(alice.address)` to undelegate; balanceOf(alice) > 0, vote power restored
**How found:** Code reading of increaseUnlockTime's conditional expiry check: noticed the 'Lock expired' require only applies on the non-delegated path, hypothesized delegation could bypass it, and confirmed with a Foundry/Hardhat script.
**Exploitation:** An expired-lock holder delegates to any address to bypass the expiry guard, extends the unlock time, then re-delegates to self to regain voting power that should have been forfeited.
**Insight:** When a guard is placed inside one branch of an if/else on delegation state, test the other branch for the same invariant; state-dependent checks are a common bypass surface in ve-token contracts.
