# ERC777 reentrancy when withdrawing can be used to withdraw all collateral

ERC777 tokensToSend hook reenters Market.withdraw before balance updates, letting a borrower drain all collateral while keeping the loan.

- Payout: Audit contest
- Severity: medium
- Program: Inverse Finance
- Found by: Lambda
- Disclosed: 2022-12-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-10-inverse#m-04
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-inverse%3AM-04
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reentrancy

**Target:** Market.sol withdraw / escrow.pay collateral transfer
**Root cause:** withdrawInternal checks the withdrawal limit via escrow.balance() before the ERC777 transfer completes; the tokensToSend hook fires before balance updates, so a reentrant withdraw sees the stale pre-transfer balance and passes the limit check again.
**Steps:**
1. Deploy market with an ERC777 collateral token; collateralFactorBps=5000.
2. Deposit 10,000 USD collateral, borrow 2,500 USD (withdraw limit 5,000).
3. Call `withdraw(5000)`; withdrawInternal passes limit check and calls `escrow.pay(to, amount)`.
4. In the ERC777 `tokensToSend` hook (before balance update), reenter `withdraw(5000)`; getWithdrawalLimitInternal reads stale escrow.balance()=10,000 and allows it.
5. Both transfers succeed; attacker receives all 10,000 collateral while retaining the 2,500 loan.
**How found:** Noticed ERC777 tokensToSend hook executes before balance updates, so escrow.balance() used in getWithdrawalLimitInternal returns stale value during reentrancy.
**Exploitation:** Attacker borrows against ERC777 collateral, then reenters withdraw from the tokensToSend hook to bypass the collateral-factor limit and extract the full collateral while keeping the outstanding debt.
**Insight:** When a market accepts arbitrary ERC20-compatible collateral, check whether limit/health calculations read live token balances; ERC777/ERC677 hooks fire pre-balance-update and can reenter stale-balance checks.

