# Wrong calculation of excess depositToken allows stream creator to retrieve depositTokenFlashloanFeeAmount, which may cause fund loss to users

Locke.sol excess-deposit math omitted depositTokenFlashloanFeeAmount, letting stream creator recover flashloan fees and leaving later depositors unable to withdraw.

- Payout: Audit contest
- Severity: high
- Program: Streaming Protocol
- Found by: WatchPug
- Disclosed: 2022-02-11
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-11-streaming-findings/issues/241
- Library page: https://bugbountylibrary.com/r/c4%3A2021-11-streaming%3AH-01
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Locke.sol streaming contract recoverTokens/claimFees accounting
**Root cause:** excess is computed as balanceOf(token) - (depositTokenAmount - redeemedDepositTokens), omitting depositTokenFlashloanFeeAmount that is owed to governance, so the fee amount is treated as recoverable surplus.
**Steps:**
1. Deploy with feeEnabled=true, feePercent=10 (0.1%).
2. Alice deposits 1,000,000 depositToken.
3. Bob flashloans 1,000,000 depositToken and repays 1,001,000 (1,000 fee).
4. Charlie deposits 1,000 depositToken.
5. After endDepositLock Alice calls claimDepositTokens() withdrawing 1,000,000.
6. streamCreator calls `recoverTokens(depositToken, recipient)` and receives 1,000 = 2,000 - (1,001,000 - 1,000,000).
7. governance calls claimFees() and takes the remaining 1,000.
8. Charlie's claimDepositTokens() reverts on zero balance; Charlie loses deposit.
**How found:** Code review of the excess balance calculation in Locke.sol line 654; noticed depositTokenFlashloanFeeAmount was not subtracted from the recoverable surplus, then constructed a flashloan-fee scenario to show double-spend of the fee.
**Exploitation:** Stream creator waits until fee accrues from a flashloan, then calls recoverTokens(depositToken, recipient); the excess formula counts the flashloan fee as surplus, so the creator withdraws it before governance claimFees(), leaving the contract short and later depositors unable to redeem.
**Insight:** When a contract tracks multiple owed buckets (user principal, protocol fees) in one token balance, audit every 'excess = balance - owed' formula for omitted buckets; flashloan fees are a classic forgotten liability that lets one party front-run another's claim.
