# _vested() claimable amount calculation error

Vesting._vested() fully-vested check ignores __initialUnlockTimeOffset, letting users claim more than _totalAmount during the offset window.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: bin2chen
- Disclosed: 2024-05-23
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-02-tapioca-findings/issues/111
- Library page: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-05
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** Vesting contract _vested() claimable amount calculation
**Root cause:** The fully-vested early return compares block.timestamp against _start + _duration without subtracting __initialUnlockTimeOffset, while the partial-vesting formula does subtract it, so the linear formula can exceed _totalAmount before the early return triggers.
**Steps:**
1. Set state: _totalAmount=500, duration=1000, __initialUnlockTimeOffset=100, start=1000.
2. At block.timestamp=1999, check `block.timestamp >= _start + _duration` → 1999 >= 2000 is false, so no early return.
3. Compute `_start = _start - __initialUnlockTimeOffset` → 900.
4. Return `(_totalAmount * (block.timestamp - _start)) / _duration` = 500*(1999-900)/1000 = 549 (549.5 truncated).
5. Call claim() to receive 549 > _totalAmount=500.
**How found:** Code reading of _vested(): noticed the fully-vested early return uses _start + _duration while the partial formula subtracts __initialUnlockTimeOffset from _start, creating an inconsistency; constructed a numeric example to confirm overclaim.
**Exploitation:** A vesting beneficiary waits until block.timestamp is within __initialUnlockTimeOffset of the nominal end (start+duration) but before it, then calls claim(); _vested returns a value above _totalAmount, so the user withdraws more tokens than allocated.
**Insight:** When a function applies an offset in one branch but not the boundary check of another, the linear interpolation can overshoot its cap; always verify the early-return threshold uses the same adjusted start as the formula.
