Skip to main content

Command Palette

Search for a command to run...

The Hacker Who Lost $7.73M to a Bot — rsETH Safe Module Exploit

Updated
6 min readView as Markdown
The Hacker Who Lost $7.73M to a Bot — rsETH Safe Module Exploit
M
Smart contract security researcher.

On September 15, 2026, someone found a bug in a custom router module attached to a Gnosis Safe holding over $7.73 million in Aave-wrapped rsETH. They built the exploit, submitted it to the mempool — and an MEV bot named Yoink copied the transaction and executed it first. The attacker showed up an hour later to scrape leftovers.

This write-up covers what I was able to verify on-chain and what I had to rely on others for. The router's source code is not published on Etherscan, so the internal vulnerability mechanism comes from SlowMist's bytecode analysis, credited below. Everything else — the Safe configuration, the money flow, the attacker timeline, and the current state — I read directly from the chain.


The Safe

Address: 0x40E93a52F6Af9fCD3b476aeDADD7FeABD9f7AbA8

A Gnosis Safe (v1.3.0) with three owners and a threshold of one:

Owner Address
Owner 1 0x8c2aeccef3b3634d039c96993577f80d3278fee8
Owner 2 0x5f411b4485741e5a437fcc1ef103fbeb461158ca
Owner 3 0xe32e3bd2ec560513cab4757564ca50d13caf9f7f

Threshold: 1-of-3. Any single owner could authorize transactions. Verified via getOwners() and getThreshold() on-chain.

The Safe had a custom module enabled: a router contract at 0x4f0055926c839D1d960a82CBF84E2eE933958ebC (2,127 bytes, source not verified on Etherscan). This module had the ability to execute transactions on the Safe without requiring owner signatures — that is the intended behavior of Safe modules. The bug was in the router's own authorization logic.

Post-exploit, the module has been removed. isModuleEnabled(0x4f0055...) currently returns false.


The vulnerability

Source: SlowMist, who identified this from bytecode analysis. I have not independently verified the router's internal logic because the source code is not published.

The router exposed a multicall(address, bytes[]) function. When called with the first argument set to address(this) (the router's own address), the inner _isAuthorized check passed because msg.sender in the inner call context was the router itself — which was an authorized module on the Safe. This allowed anyone to construct a multicall that the router would execute as if it were an authorized caller.

AstraSec and Blockaid published consistent analyses within hours.


What happened — the Yoink

Block: 25980525 Time: September 15, 2026, 04:38:47 UTC

The exploit transaction:

0x0e7680b06cb8a6f86c149d9ba90d98e3d334e7b072dde03909d43fcfd98a8705

Field Value
from 0xfde0d1575ed8e06fbf36256bcdfa1f359281455a
to 0x80bf7db69556d9521c03461978b8fc731dbbd4e4
gas used 3,207,685
logs 39 events

The from address is not the attacker. It is an MEV bot operator. The attacker (0x2f7e143e27f2fa26ef3b8ac72698f1d321422f67) submitted the exploit transaction to the public mempool. Yoink — an MEV bot — saw it, extracted the calldata, and submitted an identical transaction with a higher gas price. The bot's transaction landed in block 25980525. The attacker's original transaction was displaced.


Money flow

Reconstructed from ERC-20 Transfer event logs on the exploit TX receipt:

Step 1: Safe (0x40e93a) sends 2,900 aEthrsETH to Uni V4 / Permit2
        Token: aEthrsETH (0x2d62109243b87c4ba3ee7ba1d91b0dd0a074d7b1)

Step 2: Helper (0x10605ee48ff9...) unwraps aEthrsETH
        → burns 2,900 aEthrsETH (to 0x0000...0000)
        → receives 2,900 rsETH from Aave
        
Step 3: rsETH flows through Uni V4 to MEV bot (0x80bf7db6...)

Step 4: MEV bot distributes:
        → 2,882.3674 rsETH to Yoink wallet (0xC70f00CD7E461686b04B0E912E309becA8b80ea0)
        → 17.6326 rsETH to Uni V4 (swap fee / hook)

Total extracted from Safe: 2,900 aEthrsETH ≈ $7.73M at the time.


The attacker's timeline

The attacker (0x2f7e143e27f2fa26ef3b8ac72698f1d321422f67) has 11 total transactions, all after the Yoink. Verified from Etherscan:

Time (UTC) Action Notes
05:43:35 Contract creation Exploit contract deployment
05:43:35 Call to 0x94Fcd3... Setup
05:44:47 rsETH token call Approval (Transfer event = Approval log)
05:49:23 Contract creation Second contract
05:49:23 Call to 0x9c904c... Setup
05:49:59 Contract creation Third contract
05:49:59 Call to 0x9c904c... Setup
05:50:23 Call to 0x4C82D1... Unknown
05:51:35 Tornado Cash Router 10 ETH sent to Tornado Cash
05:58:23 Contract creation Fourth contract
05:58:23 Call to 0xe196E5... Unknown

The attacker deployed four contracts and sent 10 ETH to Tornado Cash. Between blocks 25980878 and 25980908, the attacker managed to scrape approximately 174 aEthrsETH in small increments (0.5 rsETH per transaction) from the Safe — the leftovers Yoink didn't take.


Current state

Verified via eth_call on September 15, 2026:

Address Role Balance
Safe (0x40e93a) Victim 0 ETH
Attacker (0x2f7e14) Exploit author 0.318 ETH
Yoink wallet (0xc70f00) MEV recipient 39.12 ETH
Router (0x4f0055) Vulnerable module Code exists, module removed from Safe

Safe modules: 0 enabled (router removed post-exploit). Safe threshold: still 1-of-3.

Kelp DAO froze the Yoink recipient address (0xc70f00) within hours. Kelp's core protocol and rsETH backing are not affected — this was a user-controlled Safe, not protocol infrastructure.


What I verified vs what I cited

Claim Source My verification
Block, time, TX hash On-chain ✅ Direct RPC read
TX from = MEV bot, not attacker On-chain eth_getTransactionByHash
Safe owners + threshold On-chain getOwners() + getThreshold()
Router was a Safe module On-chain isModuleEnabled() = false (removed)
Money flow (2,900 → 2,882 + 17) On-chain ✅ Transfer event logs on receipt
Attacker timeline (11 TXs) On-chain ✅ Etherscan TX list
Tornado Cash 10 ETH On-chain ✅ TX to Tornado.Cash Router
Attacker scraped ~174 rsETH On-chain alchemy_getAssetTransfers
multicall + _isAuthorized bypass SlowMist ⚠️ Cited, not independently verified (router source unpublished)
Safe module 0xea18b... AstraSec ⚠️ Cited (module removed, can't verify pre-exploit state)
Uni V4 hook pool creation Blockaid ⚠️ Cited (hook address unverified)

The real question

The multicall bypass is the vulnerability. The MEV front-run is the plot twist. But the setup that made this possible was simpler than either:

A Safe holding $7.73M with a 1-of-3 threshold and a custom module that could move funds without owner signatures. One signature to do anything. One bug in the module to bypass even that.

The attacker found the bug. The bot found the attacker. Kelp froze the bot's wallet. The money sits at 0xC70f00, paused, waiting for whatever comes next.


Analysis based on publicly available on-chain data. Router internal logic cited from @SlowMist_Team. No transactions submitted.

Sources: