# Reward rates can be changed through flash borrows

Comptroller.refreshCompSpeeds reads manipulable totalBorrows, letting a large holder flash-borrow to skew reward rates and steal rewards from other suppliers.

- Payout: Audit contest
- Severity: medium
- Program: Based Loans
- Disclosed: 2021-05-27
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-04-basedloans-findings/issues/33
- Library page: https://bugbountylibrary.com/r/c4%3A2021-04-basedloans%3AM-01
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm technique:race-window vuln:flash-loan vuln:oracle-manipulation vuln:reward-distribution

**Target:** Comptroller reward-rate refresh (refreshCompSpeeds) reading market totalBorrows
**Root cause:** Reward rates are computed from totalBorrows, which is manipulable within a block; refreshCompSpeeds only checks tx.origin is an EOA, not that borrow state is time-weighted or stable.
**Steps:**
1. Deposit large collateral and take a huge borrow in the target market to inflate totalBorrows.
2. Call `Comptroller.refreshCompSpeeds` in the same block (EOA check passes).
3. Repay the borrow and unwind the position, paying only gas.
4. Alternatively, a miner orders borrow tx, refreshCompSpeeds tx, repay tx within one block.
5. New inflated rate persists until next refreshCompSpeeds call, boosting attacker's rewards.
**How found:** Noticed reward rates are proportional to totalBorrows and that refreshCompSpeeds only enforces an EOA caller, so same-block borrow/repay (or miner tx ordering) can manipulate the snapshot.
**Exploitation:** Attacker with large capital (or a miner/flashbots bundle) sequences borrow -> refreshCompSpeeds -> repay in one block, inflating totalBorrows at refresh time so reward speeds favor markets they supply/borrow in; extra rewards are siphoned from other legitimate users at only gas cost.
**Insight:** When a rate/oracle reads a spot state variable like totalBorrows, check whether that variable can be moved within a single block by borrow/repay or miner ordering; an EOA-only check on the refresh call does not prevent same-block manipulation.

