Crypto exploits

SafeApprovalSquat exploit analysis

About $7.45M in USDC, WAVAX, WETH.e and BTC.b left a 2-of-7 Safe on Avalanche C-Chain on 26 October 2026 through unlimited approvals to an address that held the operator's contract on other chains but nothing on Avalanche. The MEV bot that took it returned all but 42,500 WAVAX, about $371K, the next day.

David

Security ·

Reported loss
$7.5M
Occurred
Logged

Logged as “2026-10-26: The Safe Held Standing Unlimited Erc20 Approvals Usdc Wavax Wethe Btcb Set 2026 03 07 And Never Revoked To A Counterfactual Address That Was Empty On Avalanche That Address Is The 13Th Create Output Of A Safe Createcall Instance Which Is Itself The Deterministic Create2 Output Of The Safe Singleton Factory Salt 0 Fixed Initcode An Erc20 Approval Is Granted To An Address Not To A Specific Caller So Any Fresh Eoa Can Reproduce The Same Create2 Then Create Math Occupy The Address And Call Transferfrom To Spend The Approvals With No Safe Key Signature Or Role on SafeApprovalSquat”.

Analysis3 min read

What the Safe had approved

On 7 March 2026 a 2-of-7 Safe on Avalanche C-Chain granted unlimited ERC20 approvals for USDC, WAVAX, WETH.e and BTC.b to an address that held no contract code, and those approvals were never revoked. On 26 October 2026 they were spent and the Safe was emptied of all four tokens. The approval transaction sits in block 79,804,885.

The approved address, 0x3725bd4d175283108156c3f15f86e1c51266155d, hosts the operator's own pool contract on Ethereum, Arbitrum and Base. On Avalanche nothing had been deployed there. The same MultiSend batch that set the approvals also called addPool (selector 0xd914cd4b) on the empty address. A call to an address with no code succeeds, so the batch executed cleanly and nothing flagged the mistake.

The address is the 13th CREATE output of a Safe CreateCall instance at 0xb22d635d552ec95142e2abe3ffb859ea7d7c0316, itself the CREATE2 output of the Safe Singleton Factory at salt 0. Anyone could deploy that instance on Avalanche, step its nonce to 13 and own the allowance.

SafeApprovalSquat is the label DeFiHackLabs gave the incident, not the name of a protocol, and no source names the Safe's owner. The proof of concept rebuilds the drain from a fresh address with no Safe key, signature or role.

The sequence

The proof of concept does it in four steps.

  1. Deploy the CreateCall instance through the Safe Singleton Factory, passing salt 0 and the exact creation code the attacker used.
  2. Call performCreate twelve times with empty runtime code to advance the instance's nonce.
  3. Call performCreate a thirteenth time with the sweeper's creation code. The new contract lands at exactly the pre-approved address, and address(this) is now the spender that the Safe's allowances point at.
  4. Call sweep on it, which pulls the Safe's full balance of each of the four tokens with transferFrom.

The transaction that landed deployed the CreateCall instance itself and carries thirteen contract-creation events from it. The thirteenth names 0x3725bd4d175283108156c3f15f86e1c51266155d, and the four transfers out of the Safe come before it, so on-chain the sweep ran in the new contract's constructor rather than in a separate sweep call.

Two transactions in one block

The attacker's own transaction and the one that succeeded sit in the same block, 98,605,391. The original, from 0x4c48b79b97516719444056d2bf0dc9564138fa0a, reverted with no logs. The copy, from the MEV bot 0x36b112875f921e51f5ea8ff39b374960694d21b3, succeeded with the same thirteen deployments and the four transfers. The bot's copy sat at position 0 in the block and the original at position 2.

The figures

DeFiHackLabs records a loss of about $7.45M: 3,078,123.681646 USDC, 351,374.076087 WAVAX, 183.747433 WETH.e and 10.773856 BTC.b. The transfer events in the transaction that landed give slightly different amounts, because the Safe kept trading between the block the reproduction forked from and the block the drain landed in. In that block, 3,090,123.580226 USDC, 350,375.855261617903021083 WAVAX, 181.976077726326658796 WETH.e and 10.786059 BTC.b left the Safe for the bot's address.

The return

On 27 October the bot's holding wallet 0x11eb9b677510e2594857f4d137fd12a7fef39bc5 sent the USDC, WETH.e and BTC.b and 307,834 WAVAX to 0x35c6aa248e9495e0572598fbfe0528acbac2807c. It kept 42,500 WAVAX, about $371K, under a settlement agreed on-chain, per AMLCrypto. Net of the return, that bounty is what the Safe lost.

What would have prevented it

Checking that the spender had code on Avalanche before approving it. The batch's addPool calls to an empty address returned success, and two signers passed it. After that, revoking the allowances, which stayed live for seven months. The 2-of-7 threshold never came into the drain.

Where this sits in the corpus

The closest case in the corpus is Magic Eden, where approvals that wallets had given a marketplace contract long out of use were spent through a bug in it. There the spender was a deployed contract with a flaw. Here the spender had never been deployed on the chain, and whoever deployed it first owned the allowance. The settlement follows Liquid Network, where the party holding the funds returned most of them and kept a bounty.

Sources read (12)

Other exploits

Query every incident yourself — free, no signup

Updated 11 Nov 2026. Figures are as reported by the sources listed above and are not independently verified.