Relayer attack analysis and mitigation

Short description

Yesterday there was an attack on relayers, the total losses amounted to more than 2 ETH, but attacker earned nothing.
The attacker’s method was that he initiated transactions to withdraw 0.1 ETH from Tornado pool through relayers, using as the recipient address a special contract that he had created earlier, which did not allow funds to be received to the contract address - as a result, such relayer transactions were failed, but the network commission for gas was debited from relayers.

Issue mitigation

Immediately after discovering the problem - thanks to @Vlados, who noticed suspicious transactions and notified me - I sent messages to all attacked relays (even before identifying the attacker and determining the exact attack vector) - I wrote to everyone whose contacts I knew in messengers, the rest were notified via onchain messages (1, 2).

A few hours later, the principle of the attack was completely clear and an emergency software patch for relayers was released - attention, ALL relays must reinstall the current software from scratch on a fresh Linux server, using the instructions in this repository.

P.S. By the way, if proposal 27 had been accepted, the current situation wouldn’t occurred - smart gas calculation checks the correctness of the transaction before execution. For the same reason, sidechains relayer software, which code has been updated, are safe - a similar method wouldn’t work there.

Full attack log

Attacker address: 0x3b96C58304e1d980B3caD36296303c303120ec16


  1. Attacker deposited 0.1 ETH to Tornado pool (this needed to generate valid withdrawal proofs): tx link
  2. Attacker created master-contract: address 0xa6cdb3cd8a27731754d7879b87cc30fc631a305e
  3. By calling a function with the e3fbf27a selector, attacker using a master contract creates 40 contracts with the same source code: tx link

These 40 contracts that will be used as recipients in withdrawal transactions during the attack.

Attacker targets:
Four relayers were attacked - default-relayer.eth, torrelayer.eth, and also first-relayer.eth via his worker address 0x864df9cd806d58341f13602103bf853066ff962a and 0xgm777.eth via his worker address 0x03392600086874456e08d2bac104380bcdebcfc0.

It is also worth noting, that all relayers with low commissions were attacked (below 0.39% on the Ethereum Mainnet), which makes it highly likely that the attacker was one of the relayers with a high commission, who was dissatisfied with dumping.

All of the attacker’s transactions are approximately identical (the full list can be seen in the address transaction log, links to which are presented above), so for example, let’s look at one transaction - 0x7bd231bef00a5943cee743aca1e026e5a0010b295e7ac3e734c081c25cd70270.
The fifth argument in the withdraw function of the Tornado Router contract is the address to which funds will be withdrawn:

Let’s check contract at this address: 0x65cebaa6f812ab4be7dc7fb1b2a8b62d548e0b60. This is one of the 40 contracts described above and since the contract, of course, is not verified, let’s decompile it and look at the called function - fallback:

Since the address in the _operator variable is non-payable, it is impossible to send the withdrawn ETH to it. v0 becomes false after call inside this contract, and call to this contract fails with the error revert(Error(v3)), however, the network commission for the transaction is still debited from the relayer. Full trace on openchain.


The total losses of the attacked relayers amounted to more than 2 ETH; first-relayer.eth suffered the most, losing approximately 1.2 ETH.
The patch was released a few hours after the attack, all relayers must reinstall the software immediately on fresh Ubuntu server using installation script from this link.

Also, some of relayers affected by the attack told me that they want to request compensation for losses using the proposal. What does the community think about this, should I create a proposal?
Let me remind you that all relayers agreed to the following conditions upon registration:

Community voting:

  • We need to return lost funds to relayers
  • What happened is one of the risks in relaying, no need to compensate
0 voters

We have more than 60% votes for returning lost funds to the relayer.
I’ll start developing a proposal after this weekends.