# Potential Loss of Rewards During Token Transfers in StaticATokenLM.sol

StaticATokenLM._beforeTokenTransfer updates user rewards with fresh=false, so unclaimed Aave rewards are skipped and the transferrer loses accrued rewards to the receiver.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: RaymondFam
- Disclosed: 2023-11-13
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-reserve-findings/issues/4
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-15
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** StaticATokenLM.sol reward-accounting wrapper over Aave AToken
**Root cause:** _updateUser calls _getPendingRewards(user, balance, false), skipping the fresh branch that pulls the latest rewards from INCENTIVES_CONTROLLER, so _accRewardsPerToken is stale when snapshots are updated during transfer.
**Steps:**
1. Read _beforeTokenTransfer: calls _updateUser(from) and _updateUser(to) on every transfer.
2. Note _updateUser invokes `_getPendingRewards(user, balance, false)`.
3. Observe the `if (supply != 0 && fresh)` block is skipped, so accRewardsPerToken is not refreshed from INCENTIVES_CONTROLLER.getRewardsBalance.
4. _updateUserSnapshotRewardsPerToken sets user snapshot to stale _accRewardsPerToken, dropping pending rewards for the sender.
5. Trigger via transfer (e.g. Backing Manager sending AToken on RToken redemption or to auction bidders) after rewards accrued since last _updateRewards/_collectAndUpdateRewards.
**How found:** Code reading of the transfer hook and reward-accounting path: noticed the `fresh=false` argument in _updateUser versus the fresh=true path used elsewhere, and traced how the skipped branch leaves _accRewardsPerToken stale before snapshot update.
**Exploitation:** Not an attack; a correctness bug. Sender's unaccounted rewards are effectively shifted to the receiver (zero-sum), with Reserve's Backing Manager losing more than it gains depending on redemption frequency and time since last reward update.
**Insight:** When a contract has a 'fresh' flag to optionally sync external reward state, check every caller: transfer hooks that pass fresh=false silently misprice rewards relative to deposit/withdraw paths that sync first.
