At 20:20:59 UTC on October 29, 2026, an attacker took control of Binance 14, one of Binance’s main Ethereum hot wallets. Three minutes and 24 seconds later, its 167,464 ETH and 1.6 billion USDT were gone. Binance now puts the total impact of the incident at about $6.3 billion and says it will cover every loss.
The takeover itself was public. For those three minutes, and for the 3 hours 49 minutes the attacker kept control, anyone could ask the Ethereum network one question about the wallet and get an answer that said it had been hijacked. We rebuilt the timeline block by block, then pointed our own monitoring at the moment of the takeover. The check failed on its first run.
What Binance has said
- A laptop, not a leaked key. Binance’s initial investigation “suggests that the security incident may involve a compromised DevOps engineer’s laptop, which allowed an attacker to gain access to a service container and submit unauthorized withdrawal transactions.” It has “found no evidence of any wallet private key leak” (Binance on X, 02:25 UTC on October 30).
- About $6.3 billion. That is Binance’s estimate of the total impact across every chain, with about $3 billion frozen on-chain so far with blockchain partners. Tether froze more than 1.56 billion USDT and Circle more than 800 million USDC (CoinDesk).
- What it has done. Binance suspended deposits and withdrawals, “revoked the affected address authorisation” and engaged law enforcement. It says losses will be covered from its SAFU fund and company funds, and it has promised a technical post-mortem and an updated proof of reserves.
The rest of this post is about one wallet on Ethereum, where the record is complete.
What the chain shows
Binance 14 is 0x28C6…1d60. These are the moments that matter, from our own queries of Ethereum mainnet. Times are block times in UTC.
| Block | UTC | What happened | Tx |
|---|---|---|---|
| 26,300,752 | 20:20:47 | An ordinary wallet: its code is empty (0x). It holds 167,445 ETH and 1.61 billion USDT. | |
| 26,300,753 | 20:20:59 | The takeover. Address 0x7c86…5ca0 sends one transaction carrying 50 EIP-7702 authorizations for the wallet. One is valid, and the wallet’s code becomes 0xef0100 followed by the address of a sweeper contract. | tx |
| 26,300,754–769 | 20:21:11–20:24:11 | Nothing else visible changes. Deposits keep arriving, and the wallet keeps sending transactions of its own. | |
| 26,300,770 | 20:24:23 | First sweep. 0x7c86…5ca0 calls the wallet, which now runs the sweeper’s code. 167,464 ETH and 1,615,409,499 USDT leave; 1 ETH stays behind. The USDT goes to 0x5227…2f8c. | tx |
| 26,300,968 | 21:04:23 | Second sweep: 1,700 ETH and 3.9 million USDT that arrived after the first. | tx |
| 26,301,167 | 21:44:11 | Third sweep: 370 ETH and 200.4 million USDT. | tx |
| 26,301,444 | 22:39:35 | Fourth sweep: 128 ETH. | tx |
| 26,301,828 | 23:56:47 | Fifth sweep: 2,962 ETH. | tx |
| 26,301,896 | Oct 30, 00:10:35 | The revoke. The wallet sends itself a transaction with one new authorization that clears the delegation, and its code is 0x again. This matches Binance’s statement that it revoked the authorization. | tx |
USDT amounts are exact, from the token’s transfer events. ETH amounts are the wallet’s balance change in each sweep block, found by sampling its balance every eight blocks, so a smaller sweep could be missing. Other tokens are not counted. Every sweep was sent by 0x7c86…5ca0, the only address the sweeper lets drain the wallet (Blockaid).
Two numbers stand out. The first sweep came 3 minutes 24 seconds after the takeover. And the takeover lasted 3 hours 49 minutes, during which the wallet kept being refilled and the attacker emptied it four more times: another 204.3 million USDT and about 5,160 ETH, all taken after the first sweep.
Why one question gives it away
Since Ethereum’s Pectra upgrade in May 2025, an ordinary account can point itself at a smart contract by signing an authorization, a feature called EIP-7702. From then on, any call to the account runs that contract’s code. Wallets use it for features like batching. This attacker used it to give Binance’s wallet a new function that sweeps its ETH and tokens such as USDT to the attacker, leaving 1 ETH behind, and that only the attacker can call.
The authorization leaves a mark. Ask any Ethereum node for the account’s code with eth_getCode: an ordinary account returns 0x, and a delegated one returns 0xef0100 followed by the 20-byte address it delegates to. The answer is public, costs nothing and changes in the same block as the takeover. Very few attack steps can be seen from outside the victim’s systems. This one can.
It also fits Binance’s preliminary account. An authorization has to be signed for the wallet, but not necessarily by someone who holds the key: whoever can get the wallet’s signing service to sign can produce one. Blockaid noted that the attacker sent 50 authorizations at once, each for a different nonce, because it could not know which nonce the busy wallet would be on when the transaction landed. One matched.
We pointed our monitoring at the takeover
Ethereum nodes answer eth_getCode for past blocks too, so the takeover can be replayed against a real check. On October 30 we created HTTP checks in our own Site Qwality account. Each sent the same request to a public Ethereum endpoint, with the block number pinned, and asserted that the answer was 0x:
- Block 26,300,752, 12 seconds before the takeover: the result was
0xand the check passed. - Block 26,300,753, the takeover: the check failed on its first run, the automatic rechecks from a second cloud failed too, and the monitor went to failed, which is what sends the alert. That was 41 seconds after we created it.
- The latest block: the check passed, because Binance has revoked the delegation.
This is the failing result as our API returned it. The dashboard shows the json_path failure reason as “JSON path mismatch”.
check_region aws-us-east-1
response_http_code 200
failure_reason json_path
response_body {"id":1,"jsonrpc":"2.0","result":"0xef010063e842b054bd624a465454d533c33f573e9c6fae"}
Run every 30 seconds against the latest block, the same check would have failed on its first run after 20:20:59, at most 30 seconds later. That is close to three minutes before the first sweep, and nearly four hours before the revoke.
How to set up the alert
You need the address of each hot wallet you want to watch, an HTTPS JSON-RPC endpoint for the chain (your own node, or your node provider’s endpoint; a public endpoint is fine for trying it) and a Site Qwality account. 30-second checks and more than one check location need a paid uptime plan; the free plan checks every 5 minutes from one location.
- Add an HTTP monitor. Name it after the wallet, such as “Hot wallet 1 code”, and enter your RPC endpoint in URL or IP.
- Set the request. Under Request, set Method to
POST, Content Type to JSON and Request Body to:{"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["0xYOUR_HOT_WALLET","latest"]} - Add the assertion. Under Advanced, set JSON path to
$.resultand JSON path expected value to0x. - Check often, from more than one place. Set Check Interval to 30 seconds and pick at least two check locations.
- Route it to someone who can act. Under Alerting, keep Confirmation Threshold at 1 and choose a notification group that reaches your on-call people, plus a signed webhook if you want your own systems to react.
- Repeat for each wallet, and on each EVM chain that supports EIP-7702 where you keep one.
Through the API, it is one request (see the HTTP check reference):
curl -X POST https://api.siteqwality.com/http/job \
-H "Authorization: Bearer $SITEQWALITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"friendly_name": "Hot wallet 1 code",
"uri": "https://YOUR_RPC_ENDPOINT",
"method": "POST",
"content_type": "json",
"request_body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getCode\",\"params\":[\"0xYOUR_HOT_WALLET\",\"latest\"]}",
"json_path": "$.result",
"json_path_expected": "0x",
"run_interval_seconds": 60,
"run_interval_thirty_seconds": true,
"timeout_ms": 10000
}'
A few things make it better:
- Use two providers. One check trusts one endpoint. A second monitor against a different provider means a provider that lags or misbehaves cannot hide the change.
- If you use EIP-7702 on purpose, set the expected value to your own delegation,
0xef0100followed by your contract’s address in lowercase hex. The check then fails if the wallet ever points anywhere else. - Read the failure reason. “JSON path mismatch” means the code changed. A timeout or an HTTP error means the endpoint is down, which you also want to know but is not a takeover.
What an alert can and cannot do
- It does not stop a sweep by itself. Three minutes is short for a person and long for software. A webhook into a runbook that freezes outgoing transfers and refills for the wallet, and pages the team, fits inside it.
- The cheapest win is everything after the first sweep. The wallet kept receiving funds for almost four hours, and 204.3 million USDT and about 5,160 ETH were taken after the first sweep. Stopping refills to a wallet whose code has changed needs no access to the attacker’s contract, only to your own systems.
- It watches one kind of takeover. An attacker who controls the signer can also simply send transfers, with no change to the wallet’s code. Catching that takes transaction monitoring on your own side. Watching the code is cheap, runs outside your infrastructure and catches exactly the step used here.
- We do not know what Binance was watching. Binance runs its own monitoring and may have seen the takeover at once; its post-mortem should say. The point is narrower: the signal was public and simple, and anyone holding funds in an ordinary Ethereum account can watch it today.
Same afternoon, different attack
Binance’s takeover came a little over three hours after the Polymarket DebugBear hack began, and nothing links the two. They do rhyme. In neither case did the attacker steal a key. At Polymarket, a compromised monitoring script got the page’s own signer to sign; at Binance, by its own account, access to a service container got the wallet’s signer to sign. When the signer is the target, watch what it signs and what it changes, from somewhere the attacker cannot reach.
Sources
- Binance: preliminary statement on X and announcement (October 30, 2026)
- Blockaid: the sweeper contract and the 50 authorizations (October 29, 2026)
- CoinDesk: Potential multi-billion Binance hack hitting crypto markets (October 29, 2026)
- Blockhead: Binance halts withdrawals after multibillion-dollar hot wallet drain (October 30, 2026)
- TechCrunch: Binance pauses withdrawals as hackers suspected of stealing billions in crypto (October 29, 2026)
- EIP-7702: Set Code for EOAs
- On-chain data: our own
eth_getCode,eth_getBalance, transaction and USDT transfer-log queries for Binance 14 (0x28C6…1d60) on Etherscan, blocks 26,300,723 to 26,301,946.