# Incomplete Share Removal on Withdraw Causes Unclaimed Rewards and Broken Share Logic

UnwindingModule.withdraw only subtracts a user's initial shares from totalShares, leaving reward-minted shares as phantom shares that dilute share-to-asset accounting and strand rewards.

- Payout: Contest reward
- Severity: high
- Program: infiniFi
- Credited: aksoy
- Disclosed: 2025-05-23
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_infinifi_april2025.pdf#3.1.2
- Library page: https://bugbountylibrary.com/r/cantina%3Ainfinifi_april2025%3A3.1.2
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:cantina sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** UnwindingModule.sol
**Root cause:** withdraw deducts only position.shares from totalShares while totalReceiptTokens is reduced by the full userBalance, so reward shares minted via depositRewards are never removed.
**Steps:**
1. Create position for alice with 1000 shares, start unwinding, advance one epoch so totalShares=1000
2. Call `_depositRewards(100)`; totalShares becomes 1100
3. Advance past unwinding period and call `gateway.withdraw(startUnwindingTimestamp)`
4. Observe totalReceiptTokens()==0 but totalShares()==100 (phantom shares remain)
5. Repeat with bob: after second cycle totalShares()==210 while totalReceiptTokens()==91, showing asset/share mismatch
**How found:** Code reading of withdraw vs depositRewards: noticed totalShares += rewardShares on deposit but withdraw only does totalShares -= position.shares, then wrote a Foundry PoC to confirm leftover shares.
**Exploitation:** Normal withdrawal path leaves unclaimed reward shares in totalShares; repeated cycles inflate totalShares relative to assets, decaying asset-per-share and misallocating future reward distributions.
**Insight:** When a contract mints shares for rewards into a global totalShares, audit every burn path to confirm it removes the full balanceOf-derived share amount, not just the principal recorded in the position struct.
