# transferVesting creates an incorrect vesting for new users when they purchase a vesting, because stepsClaimed is the same for all sales, allowing an attacker to prematurely unlock too many tokens

VestingManager's pooled vesting stores a single stepsClaimed from the first sale, so new buyers inherit a stale value and can claim unlocked tokens immediately.

- Payout: Contest reward
- Severity: high
- Program: SecondSwap
- Credited: TheSchnilch
- Disclosed: 2025-02-18
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2024-12-secondswap#h-02
- Library page: https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** SecondSwap_StepVesting / SecondSwap_VestingManager vesting transfer
**Root cause:** All sold vestings are pooled at the VestingManager address, which keeps only one stepsClaimed value (from the first sale) that never updates while totalAmount > 0; transferVesting copies this stale value to new buyers.
**Steps:**
1. Deploy StepVesting with 10 steps over 10 days; admin creates 1000 token vesting.
2. Admin lists 100 tokens via `marketplace.listVesting(...)`; VestingManager vesting stepsClaimed = 0.
3. Alice `spotPurchase` 50 tokens; totalAmount stays >0 so stepsClaimed remains 0.
4. Warp 5 days; Alice `vesting.claim()` gets 25 tokens (half unlocked).
5. Alice lists remaining 25 tokens; stepsClaimed still 0.
6. Bob (no prior vesting) `spotPurchase` 25 tokens; inherits stepsClaimed=0.
7. Bob calls `vesting.claim()` and immediately receives unlocked tokens without waiting.
**How found:** Code reading of transferVesting and claim logic: noticed VestingManager pools all sold vestings under one stepsClaimed that only resets when totalAmount hits 0, so buyers adopt a stale value.
**Exploitation:** Attacker waits until a portion unlocks, claims it, sells the remainder, then buys back from a fresh address with no vesting to inherit stepsClaimed=0, repeating to unlock tokens early.
**Escalation:** Repeat sell/buy cycle across multiple fresh addresses to progressively unlock more tokens ahead of schedule.
**Insight:** When a contract pools many user positions under one shared accounting variable, check whether per-position state (like stepsClaimed) is preserved on transfer or silently inherited from the pool's first entry.
