# User can alter amount returned by redeem function due to control transfer

ERC777 burn hook during redeem lets receiver move tokens mid-call, corrupting balanceBefore/After so redeem returns a wrong (even zero) asset amount.

- Payout: Contest reward
- Severity: medium
- Program: Notional
- Credited: 0xDjango
- Disclosed: 2022-07-18
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-06-notional-coop-findings/issues/235
- Library page: https://bugbountylibrary.com/r/c4%3A2022-06-notional-coop%3AM-10
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:reentrancy

**Target:** ERC4626-style redeem function wrapping ERC777 asset
**Root cause:** redeem measures assets as balanceAfter - balanceBefore around _redeemInternal, but _burn on the ERC777 transfers control to the receiver, who can move tokens during that window and corrupt the delta.
**Steps:**
1. Call `redeem(shares, receiver, owner)` where asset() is an ERC777.
2. Contract records `balanceBefore = balanceOf(receiver)`.
3. `_redeemInternal` calls `_burn`, triggering ERC777 hook to receiver.
4. In the hook, transfer the received ERC777 out to another account.
5. Return to redeem; `balanceAfter - balanceBefore` is now reduced or zero, so returned `assets` is wrong.
**How found:** Warden traced that _redeemInternal calls _burn on an ERC777, which invokes a receiver hook (control transfer) between the balanceBefore and balanceAfter reads, invalidating the delta calculation.
**Exploitation:** Receiver uses the ERC777 burn hook to move the just-received tokens out before balanceAfter is read, making redeem report a deflated/zero asset amount; affects accounting/return value of redeem.
**Insight:** When a function computes a delta via balanceOf before/after an internal call, check whether any token involved has transfer/burn hooks (ERC777, ERC677) that hand control to the user inside that window.
