# Beanstalk Logic Error Bugfix Review

Beanstalk TokenFacet transferTokenFrom skipped allowance checks for EXTERNAL transfers, letting anyone drain tokens from users who approved the contract.

- Payout: $181,850
- Severity: critical
- Program: Beanstalk
- Disclosed: 2023-02-15
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/beanstalk-logic-error-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-beanstalk-logic-error-bugfix-review
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** TokenFacet transferTokenFrom in Beanstalk diamond proxy (Ethereum)
**Root cause:** transferTokenFrom only spent allowance when the sender's internal balance decreased; EXTERNAL-to-EXTERNAL transfers bypassed LibBalance accounting entirely, so no allowance was checked before token.safeTransferFrom(sender, recipient, amount).
**Steps:**
1. Victim calls `bean.approve(beanstalk, amount)` granting the Beanstalk contract ERC20 allowance.
2. Attacker calls `beanstalk.transferTokenFrom(bean, victim, attacker, victimBalance, From.EXTERNAL, To.EXTERNAL)`.
3. LibTransfer.transferToken takes the EXTERNAL/EXTERNAL branch and calls `token.safeTransferFrom(victim, attacker, amount)`.
4. Internal balance delta is zero, so `LibTokenApprove.spendAllowance` is never invoked; attacker receives victim's tokens.
**How found:** Whitehat reviewed the TokenFacet library and noticed the allowance spend was gated on an internal-balance delta, which is zero for pure EXTERNAL transfers, implying the ERC20 allowance path was unchecked.
**Exploitation:** Attacker needs no capital or approval of their own; any EOA/contract that had approved the Beanstalk contract is drainable by calling transferTokenFrom with EXTERNAL from/to modes and the victim as sender, moving the victim's full approved balance to the attacker.
**Insight:** In diamond-proxy/facet designs, audit every branch of transfer-mode enums: allowance accounting tied to internal balance deltas silently skips checks when both modes are EXTERNAL, so test each From/To combination against a victim who approved the proxy.
