# maxSellPercent can be buypassed by selling previously bought vestings at a later time

SecondSwap VestingManager sellLimit counts all previously bought tokens, letting a buyer sell more unvested tokens than maxSellPercent allows.

- Payout: Contest reward
- Severity: medium
- Program: SecondSwap
- Credited: BenRai
- Disclosed: 2025-02-18
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-12-secondswap#m-11
- Library page: https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-11
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** SecondSwap_VestingManager.listVesting sell-limit logic
**Root cause:** sellLimit starts at userAllocation.bought, so tokens bought earlier are always sellable regardless of how many steps have since unlocked, ignoring maxSellPercent on the remaining locked allocation.
**Steps:**
1. Set vesting: 1000 tokens, 10 steps, maxSellPercent=20%.
2. Alice holds 100 tokens; buys all 180 listed tokens before step 1 (bought=180, total=280, 28/step).
3. After 4 steps Alice claims 112, remaining 168.
4. Intended sell cap = (1000-400)*20% = 120, but sellLimit=180 lets her sell all 168 remaining.
5. Call `listVesting()` to sell 168 > 120 cap.
**How found:** Code review of sellLimit computation in listVesting; noticed `sellLimit = userAllocation.bought` never decays as steps unlock, contradicting the stated maxSellPercent semantics.
**Exploitation:** Buy listed vestings early to inflate `bought`, wait for steps to unlock, then list/sell the full remaining allocation exceeding the maxSellPercent cap on unvested tokens.
**Insight:** When a cap is expressed as a percentage of *remaining locked* tokens, any accumulator seeded from lifetime totals (bought) will drift; check that limit bases are recomputed against current step state, not historical purchase amounts.
