On 2026-09-08, an attacker on Ethereum used a permissionless `createOrderForBuyer` entry on an Order Factory contract to drain five buyers for ~20.247 ETH in a single transaction, part of a ~24.7 ETH reported incident.
Logged as “2026-09-08: Missing Access Control On Createorderforbuyer Drains Buyer Accounts on OrderFactory”.
An Ethereum Order Factory contract let any caller create an order "for" an arbitrary buyer, as long as the buyer's stored request was in the active state. The entry (createOrderForBuyer, selector 0xbde886fc) checked only that one condition. It did not check msg.sender == buyer, did not require a buyer signature or nonce, and did not validate the attacker-supplied seller argument. Once the call went through, the factory moved the buyer's entire ETH balance from the Account System into a freshly created order proxy, and wrote the attacker-supplied seller address into the order's privileged slot. The attacker (the seller) then called the order's abort(address) to send the proxy's full ETH balance to an address it controlled. One transaction drained many buyers.
The attacker (EOA 0x77071d2bbd8f3c296c8cd7d0abd21bc172420cda, via helper 0xde26cf7c...) carried out the drain in a single transaction on block 25933639. The factory at 0xa27bcd590195b2a9bdc29379De4F040b2D8066e0 and the Account System at 0xFcF3d97c6Db4C3bF6020a2b99af074B595bDA163 are both unverified on Etherscan; the analysis is from the transaction trace and direct state reads rather than from verified source. The factory deployed each order proxy via the deployer at 0xDd3068d772764443E4c4B18B8c96AeE153D83056 using CREATE.
The five buyers drained in the same transaction were 0x448F48d9149c3Eb7154019Efefa6A7Bf2BD58753 (10.05 ETH), 0x8F7dB8128FAE33915d47709074E2391e37A71136 (5.05 ETH), 0x5C8D3b20f52993C7f553Dd2bBf5d062b7CfC17D1 (3.05 ETH), 0x9D8f6E98d6ebe13B424386677BCF4b80dB0c6729 (1.547 ETH), and 0x3eD7571B72ffBF0d44b741b49b597791b70e145D (0.55 ETH). Each amount matches accountBalances(buyer) exactly, confirming the factory pulled the buyers' full balances into the new order proxies rather than any capped or partial value.
Once the orders existed, the attacker invoked abort(to) from the seller slot it had planted. The order's authorization check matched the attacker-supplied seller against that slot, so abort forwarded the proxy's full ETH balance to the named recipient. Because the same seller was authorized to call abort on every newly created order, the attacker drained five buyers in one transaction. The README records the full incident at ~24.7 ETH; this single transaction accounts for 20.247 ETH of that figure.
The fix is straightforward in concept: createOrderForBuyer should require the caller to prove authorization from the named buyer, either by checking msg.sender == buyer or by validating an EIP-712 signature from the buyer against a stored nonce. The order's privileged slot should likewise be set from the buyer's authorized seller list, not from any caller-supplied argument.
Query every incident yourself — free, no signup
Updated 14 Oct 2026. Figures are as reported by the sources listed above and are not independently verified.