# Vesting offset omitted from end check

Do vesting end, cancel, and transfer checks use the same cliff and initial-release offsets as the claim formula?

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2025-02-18. Updated 2026-10-25._

## How it works
A vesting schedule has several offsets: a cliff, an initial release, and a reserved offset. The claimable formula subtracts these from the start time before interpolating. A second function — the fully-vested early return, an admin cancel check, or a transfer balance check — recomputes the end or remaining amount using a simpler formula that drops one or more offsets. The two formulas disagree, so one branch treats the schedule as finished (or the balance as larger) before or after it really is. The linear interpolation then overshoots its cap, or tokens that are already the beneficiary's are treated as still movable.

## Where it shows up
- A `_vested()`/`claimable()` function with an early return for fully vested, plus a partial branch that subtracts an offset the early return does not.
- Admin `cancel`/`revoke` functions whose end-time check differs from the claimable end-time formula.
- Transfer or clawback checks comparing against `totalAmount - amountClaimed` instead of subtracting vested-but-unclaimed amounts.
- Any place `start + duration` appears without the cliff or initial-release terms added.

## How to review
Find every function that computes an end time, a remaining balance, or a claimable amount. Diff their formulas term by term. The invariant: the fully-vested threshold, the cancel end check, and the transferable-balance check must each use the same adjusted start (start plus cliff plus initial release plus reserved offset) as the claim formula, and the claimable amount must never exceed the total. Build a numeric example at the boundary where the offset window ends and confirm the early return fires exactly when the linear formula reaches the cap.

## Variants seen
- Fully-vested early return omits the initial-unlock offset, letting claims exceed the total during the offset window [E1](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-05.md).
- Cancel check uses only `startTime + period`, omitting initial release and cliff, so ongoing vesting cannot be cancelled [E2](https://bugbountylibrary.com/r/sherlock%3A2023-12-truflation%3AM-1.md).
- Transfer check subtracts only claimed amounts, so already-vested-but-unclaimed tokens can be moved away from the beneficiary [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-10.md).

## Impact and severity
Over-claiming beyond the total [E1](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-05.md), blocked admin cancellation [E2](https://bugbountylibrary.com/r/sherlock%3A2023-12-truflation%3AM-1.md), and loss of vested tokens from a beneficiary [E3](https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-10.md). Severity rises when the offset window is long or the affected balance is large; the bugs are silent because each function looks correct in isolation.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-05.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-12-truflation%3AM-1.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-12-secondswap%3AM-10.md
