# BondNFT.sol#claim() needs to correct all the missing epochs

BondNFT.claim() only updates accRewardsPerShare for the current epoch, skipping epochs between bond expiry and now, causing inaccurate reward accounting and locked/lost yield.

- Payout: Contest reward
- Severity: medium
- Program: Tigris Trade
- Credited: \_\_141345\_\_
- Disclosed: 2023-02-17
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-12-tigris-findings/issues/392
- Library page: https://bugbountylibrary.com/r/c4%3A2022-12-tigris%3AM-14
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** BondNFT.sol claim() reward accounting
**Root cause:** When an expired bond is claimed, only accRewardsPerShare[asset][currentEpoch] is adjusted for the expired shares; epochs between bond.expireEpoch-1 and current epoch are never corrected, leaving stale per-share reward values.
**Steps:**
1. Deploy/observe BondNFT with a bond that expires at epoch N while current epoch advances to M > N.
2. Call claim(_id) after expiry; code computes _pendingDelta using accRewardsPerShare at current epoch minus at expireEpoch-1 and adds only to accRewardsPerShare[asset][epoch[asset]].
3. Epochs N..M-1 retain inflated accRewardsPerShare including the expired bond's shares.
4. Other users claiming based on those intermediate epochs get wrong pending rewards; some lose yield, some over-receive, remainder locked.
**How found:** Code review of claim()'s expired-bond branch: noticed only the latest epoch's accRewardsPerShare is amended, then cross-referenced idToBond() which reads accRewardsPerShare at expireEpoch-1, revealing the gap across intermediate epochs.
**Exploitation:** Not weaponized; accounting flaw causes mispriced reward distribution across epochs when expired bonds are claimed late, resulting in yield loss for some users and locked rewards.
**Insight:** In per-epoch accumulator designs, check that any correction for expired/removed shares is applied to every epoch whose accumulator is later read, not just the current one; compare the write path against every read path (e.g. idToBond) to spot skipped indices.
