# A single second in an epoch makes an user eligible for the entire epoch's rewards

TOLP tracks lock expiry in seconds while TOB uses epochs, letting a user lock for one second of an epoch yet claim that epoch's full rewards after exiting.

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

**Target:** TOB/TOLP option reward contracts
**Root cause:** TOLP records lock duration in seconds while TOB converts expiry to epochs via _timestampToWeek; the two disagree on whether a position is active, so a lock expiring mid-epoch is treated as expired for exit but active for reward claims.
**Steps:**
1. Alice locks LP in TOLP with lockDuration such that lockTime+lockDuration lands 1 second into the next epoch (e.g. current ts 100, epoch ends 200, duration 101).
2. TOB computes lastEpoch = _timestampToWeek(201) = 2, making her eligible for all of epoch 2's rewards.
3. After ts 201, exitPosition passes (block.timestamp >= lockTime+lockDuration) so she withdraws TOLP.
4. exerciseOption still sees epoch <= expiryWeek (2 <= 2), so she claims epoch 2 rewards with no tokens locked.
**How found:** Noticed TOLP stores lockDuration in seconds while TOB converts to epochs, then compared the exitPosition timestamp check against exerciseOption's epoch-based liveness check and found they disagree mid-epoch.
**Exploitation:** Attacker times a minimal lock to straddle an epoch boundary, exits immediately after expiry to recover TOLP, then claims the full epoch's option rewards while holding nothing locked.
**Insight:** When two contracts in one system measure time in different units (seconds vs epochs/weeks), compare every liveness/expiry check across them; boundary-straddling positions can be simultaneously expired and active.
