All incidents

Balancer Callback Drain

Share
Feb 07, 2026 01:02 UTCAttackLoss: 0.47 WETH, 200 USDC +2 morePending manual check8 exploit txWindow: 41d 5h
Estimated Impact
0.47 WETH, 200 USDC +2 more
Label
Attack
Exploit Tx
8
Addresses
1
Attack Window
41d 5h
Feb 07, 2026 01:02 UTC → Mar 20, 2026 06:44 UTC

Exploit Transactions

TX 1Arbitrum
0x274c740fb476377fe731d6f7aff0c9dbeee0cac79d3a2256584de76166a20648
Mar 20, 2026 06:44 UTCExplorer
TX 2Arbitrum
0x830080c09594d75c66f78deccb83c01835aba6ddc2da566e91eca8570df71081
Mar 10, 2026 01:44 UTCExplorer
TX 3Arbitrum
0xd7e159d1ead5800493fbeb21dfcae23596e736e4b48cdc72d849bd0aab43b875
Feb 25, 2026 01:29 UTCExplorer
TX 4Arbitrum
0x902db35e54a12bbc100eb62ecddbdffb0e04bf8327970f5640566fe1cf8e8ac4
Feb 25, 2026 00:57 UTCExplorer
TX 5Arbitrum
0xa7874f4d57bed8eb80fdef8c4073540cdbb952fd0075fe3e07beb923ed6d03d6
Feb 24, 2026 02:18 UTCExplorer
TX 6Arbitrum
0xc990268a773cac177eff4340910a8c32d4109a54f39d282a05ced11f58e1a1d5
Feb 23, 2026 08:37 UTCExplorer
TX 7Arbitrum
0xb6431825b6885d28c0df71365345f4869ce97f126ba6fc8b89ff4b9a507e5882
Feb 22, 2026 01:09 UTCExplorer
TX 8Arbitrum
0x6a1c269b50fde4318f3fe3679633461044efd55a90cdf05b76acc068d358d99c
Feb 07, 2026 01:02 UTCExplorer

Victim Addresses

0x79776f9237b686dbffc0a7c629b86d575ca8ca0aArbitrum

Loss Breakdown

0.467987WETH
200USDC
30.68USDT
35ARB

Similar Incidents

Root Cause Analysis

Balancer Callback Drain

1. Incident Overview TL;DR

On Arbitrum block 443689594, attacker EOA 0xa54408e0084f6b536ae9cbaad08895973d4a31d5 deployed ephemeral contracts and used Balancer Vault flashLoan to invoke the victim helper contract 0x79776f9237b686dbffc0a7c629b86d575ca8ca0a as the flash-loan recipient. The helper then executed attacker-controlled callback data, transferred its WETH and USDC into the attacker receiver, and the receiver forwarded the proceeds to the attacker EOA.

The root cause is an authorization failure in the helper's Balancer flash-loan callback. receiveFlashLoan(address[],uint256[],uint256[],bytes) trusted any callback coming from Balancer Vault and decoded attacker-controlled userData without verifying that the flash-loan request was initiated or approved by the helper owner.

2. Key Background

Balancer Vault flash loans are permissionless. Any EOA or contract can call flashLoan and nominate an arbitrary recipient contract. Under Balancer's standard flow, the Vault then calls that recipient's receiveFlashLoan callback.

The victim is an unverified helper or smart-wallet-style contract at 0x79776f9237b686dbffc0a7c629b86d575ca8ca0a. Its disassembly shows hard-coded addresses for Balancer Vault 0xba12222222228d8ba445958a75a0704d566bf2c8, Aave pool 0x794a61358d6845594f94dc1db02a252b5b4814ad, and owner 0x88229ecb1eb6a526dc7c45940305c2b5f583af89.

The helper did contain direct owner-gated control paths. In the disassembly, the path beginning near offset 0x0342 checks the caller against the hard-coded owner before performing token approvals:

00000342: JUMPDEST
00000343: CALLER
...
0000034c: PUSH32 0x00000000000000000000000088229ecb1eb6a526dc7c45940305c2b5f583af89
0000036e: EQ
0000036f: PUSH2 0x038b
00000372: JUMPI
...
0000038f: PUSH4 0x095ea7b3

That makes the callback path important: it bypassed the helper's intended authorization boundary.

3. Vulnerability Analysis & Root Cause Summary

This incident is an ATTACK, not a benign MEV opportunity. The helper exposed a Balancer flash-loan callback that authenticated only the immediate caller, not the strategy initiator. Because Balancer flash loans are public, an unprivileged attacker could ask Balancer to call the helper directly. Once inside receiveFlashLoan, the helper decoded attacker-controlled userData and dispatched attacker-chosen external calls against the helper's own balances. That let the attacker move WETH and USDC out of the helper without ever satisfying the helper's owner checks. The broken invariant is: only the helper owner or an owner-authorized strategy path should be able to transfer or route helper-held assets. The code-level breakpoint is the callback path behind selector 0xf04f2707, which leads into the vulnerable logic around offset 0x0f53.

4. Detailed Root Cause Analysis

The helper's dispatcher routes selector 0xf04f2707 to the Balancer callback logic:

0000004a: PUSH4 0xf04f2707
0000004f: EQ
00000050: PUSH2 0x0323
...
0000033e: PUSH2 0x0f53
00000341: JUMP

The exploit transaction 0x274c740fb476377fe731d6f7aff0c9dbeee0cac79d3a2256584de76166a20648 shows the full permissionless path. The attacker-created wrapper contract deployed a receiver contract and called Balancer Vault flashLoan with the victim helper as recipient and a zero ARB amount. Balancer then invoked:

victim_helper::receiveFlashLoan([ARB], [0], [0], userData)

Inside that callback, the helper transferred its full WETH balance to the attacker receiver and then executed attacker-directed logic on the receiver:

weth::transfer(DrainReceiver, 94000000000000000)
DrainReceiver::fallback()
DrainReceiver::fallback(false, victim_helper)
weth::transfer(attacker, 94000000000000000)

The transaction receipt independently confirms the same asset flow. It records WETH transfer 0x7977... -> 0x8a8a7159... for 0x014df48080e30000, then 0x8a8a7159... -> 0xa54408e0... for the same amount, plus USDC transfer 0x7977... -> 0x8a8a7159... for 0x0bebc200, then onward to the attacker EOA. These transfers are only possible because the callback accepted attacker-controlled userData without binding it to an owner-approved initiator or trusted strategy contract.

The exploit conditions are straightforward and permissionless:

  1. The helper holds transferable token balances.
  2. The helper remains callable by Balancer Vault through receiveFlashLoan.
  3. The attacker can deploy a compatible receiver contract and encode malicious callback data.

With those conditions satisfied, the attack is deterministic.

5. Adversary Flow Analysis

The attacker flow begins with EOA 0xa54408e0084f6b536ae9cbaad08895973d4a31d5, which deployed wrapper contract 0x88bf1390314c22fb1e745910b8b4fcdde8431e8b in tx 0x274c740fb476377fe731d6f7aff0c9dbeee0cac79d3a2256584de76166a20648. The wrapper created receiver 0x8a8a71590d6a8b0bb9213ef55755b1594c66382b, then invoked Balancer Vault flashLoan with recipient 0x79776f9237b686dbffc0a7c629b86d575ca8ca0a.

The on-chain execution sequence is:

  1. Attacker deploys wrapper and receiver.
  2. Receiver requests a zero-amount Balancer flash loan with the victim helper as callback recipient.
  3. Balancer Vault calls receiveFlashLoan on the helper.
  4. The helper transfers helper-held WETH and USDC into the attacker receiver and executes attacker-controlled sub-dispatch.
  5. The receiver forwards drained assets to attacker EOA 0xa54408e0084f6b536ae9cbaad08895973d4a31d5.

The same strategy was repeated across later attacker-crafted transactions listed in all_relevant_txs, but tx 0x274c740f... is sufficient to prove the root cause and the ACT exploitability.

6. Impact & Losses

The helper and its owner suffered direct token theft. The collected receipts show aggregate attacker inflows across the exploit set of:

  • WETH: 467987463873607137 raw units
  • USDC: 200000000 raw units
  • USDT: 30682753 raw units
  • ARB: 35000000000000000000 raw units

The victim-side effect in tx 0x274c740f... is visible immediately: the helper's WETH balance is drained to zero and its USDC is transferred into the attacker path. The attacker pays only normal gas costs in ETH, which are materially smaller than the received token value.

7. References

  • Exploit tx: 0x274c740fb476377fe731d6f7aff0c9dbeee0cac79d3a2256584de76166a20648
  • Victim helper: 0x79776f9237b686dbffc0a7c629b86d575ca8ca0a
  • Balancer Vault: 0xba12222222228d8ba445958a75a0704d566bf2c8
  • Owner address embedded in helper bytecode: 0x88229ecb1eb6a526dc7c45940305c2b5f583af89
  • Helper disassembly cited in the package
  • Call trace and receipt for tx 0x274c740f..., which show Balancer invoking the helper callback and the subsequent WETH and USDC transfers into the attacker path