# Fee-on-transfer token donations in Shelter break withdrawals

Shelter.donate credits full _amount for fee-on-transfer tokens, over-reporting savedTokens; last withdrawer's share exceeds actual balance, blocking withdrawal.

- Payout: Audit contest
- Severity: medium
- Program: Concur Finance
- Found by: cmichel
- Disclosed: 2022-05-24
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-02-concur-findings/issues/180
- Library page: https://bugbountylibrary.com/r/c4%3A2022-02-concur%3AM-07
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Shelter.sol donate/withdraw share accounting
**Root cause:** donate adds the nominal _amount to savedTokens instead of the actual received balance delta, so savedTokens over-reports for fee-on-transfer tokens; withdraw computes shares against this inflated storage value.
**Steps:**
1. Deploy/use a fee-on-transfer ERC20 and activate it in Shelter.
2. Call `donate(token, amount)`; contract receives amount - fee but `savedTokens[token] += amount`.
3. Multiple users donate and withdraw; each withdraw computes `savedTokens[token] * shareOf / totalShare`.
4. Last withdrawer's computed amount exceeds contract balance; `safeTransfer` reverts.
**How found:** Code reading of donate/withdraw: noticed savedTokens is incremented by the requested amount rather than the post-transfer balance delta, and that withdraw derives amounts from this storage variable.
**Exploitation:** Any donor using a fee-on-transfer token inflates savedTokens; the final withdrawer cannot withdraw because the computed share exceeds the real balance, locking funds.
**Insight:** When a contract credits deposits by the requested amount, check whether the token can deliver less than requested (fee-on-transfer, rebasing); compare against balance delta and test the last-withdrawer edge case.
