# Reentrancy abuse to reduce the minted management fees when changing an adapter

Reentrancy via hookable token during deposit lets attacker call changeAdapter early, minting ~33% fewer management fee shares to feeRecipient.

- Payout: Contest reward
- Severity: medium
- Program: Popcorn
- Credited: 0xNineDec
- Disclosed: 2023-09-07
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-01-popcorn-findings/issues/244
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AM-28
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained vuln:accounting-error vuln:fee-bypass vuln:reentrancy

**Target:** Vault.sol changeAdapter/takeFees with hookable ERC20 asset
**Root cause:** changeAdapter() lacks nonReentrant and takeFees() reads totalAssets() before deposit's safeTransferFrom completes, so a token transfer hook reenters with stale balances.
**Steps:**
1. Deploy vault with hookable ERC20 asset and management fee > 0
2. proposeAdapter(newAdapter); warp past quitPeriod
3. In token _beforeTokenTransfer hook, call vault.changeAdapter() once
4. Call vault.deposit(10 ether, bob) to trigger hook reentrancy
5. Observe minted fee shares ~7.119e16 vs ~1.06e17 non-reentrant (~33% less)
**How found:** Noticed takeFees() is invoked by non-access-controlled changeAdapter() and deposit() mints shares before safeTransferFrom, so a token hook could reenter with outdated totalAssets.
**Exploitation:** Attacker controls a hookable token transfer hook; on deposit, hook reenters changeAdapter() which runs takeFees() against pre-transfer totalAssets, minting reduced management fee shares to feeRecipient, then outer flow completes.
**Insight:** When a fee-accrual modifier reads totalAssets() and is reachable from a nonReentrant function that mints before pulling tokens, check whether a token transfer hook can reenter the fee path with stale balances.
