# Hack Analysis: the Hundred Finance Heist, March 2022

Gnosis bridged tokens' onTokenTransfer hook let an attacker reenter Hundred Finance's Compound fork before debt was recorded, borrowing far beyond collateral and draining ~$6M.

- Payout: Real-world hack
- Severity: critical
- Program: Hundred Finance
- Credited: Immunefi
- Disclosed: 2022-09-28
- Write-up quality: 8/10
- Original: https://immunefi.com/blog/bug-fix-reviews/hack-analysis-the-hundred-finance-heist-march-2022/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-hack-analysis-the-hundred-finance-heist-march-2022
- Tags: domain:web3 impact:funds-loss kind:incident platform:immunefi sev:critical tech:evm tech:solidity technique:chained technique:source-review vuln:flash-loan vuln:reentrancy

**Target:** Compound-fork lending protocol on Gnosis Chain (hUSDC/hXDAI markets)
**Root cause:** Borrowed tokens are transferred out before the borrower's debt is written to storage, and Gnosis bridged tokens invoke an onTokenTransfer callback on the recipient, allowing reentrancy before debt accounting.
**Steps:**
1. Flash-borrow all USDC from SushiSwap WXDAI-USDC pair via `pair.swap(..., abi.encode("0x"))`
2. In `uniswapV2Call`, approve and `mint(balance)` into hUSDC market to post ~$2M collateral
3. Call `hUSDC.borrow(90% of collateral)`; the USDC transfer triggers `onTokenTransfer` on attacker contract
4. In `onTokenTransfer`, if `_from != pair` and not yet borrowed, call `hXDAI.borrow(60% of collateral)` before debt is recorded
5. Convert received xDAI to WXDAI via `deposit()`, swap to USDC on Curve 3pool `exchange(0,1,...)`
6. Repay Sushi flashloan `amount*1000/997+1` and keep remaining USDC as profit
**How found:** Recognized that Gnosis bridged tokens implement an onTokenTransfer post-transfer hook, and that Compound's doTransferOut sends borrowed funds before updating accountBorrows — a classic checks-effects-interactions violation exploitable via the non-standard token callback.
**Exploitation:** Attacker flash-borrowed ~$2M USDC from SushiSwap, deposited as collateral in Hundred's hUSDC market, borrowed 90% back, and used the ERC667 onTokenTransfer callback fired during the borrow transfer to reenter and borrow ~$1.2M xDAI from the hXDAI market before the first debt was recorded. Proceeds were swapped via Curve and the flashloan repaid, netting ~$1M in the PoC; the real attack drained ~$6M across all markets.
**Escalation:** Reentering across multiple lending markets (not just two) to drain all available liquidity, since Compound-fork markets are not isolated.
**Insight:** When a Compound fork is deployed on a chain whose canonical bridged tokens have transfer hooks (ERC667/ERC777-style), every borrow becomes a reentrancy vector because doTransferOut precedes debt storage writes; check token transfer semantics on the target chain, not just the fork's code.
