How to Check and Remove a Malicious EIP-7702 Delegation
Since the Pectra upgrade went live on Ethereum mainnet in May 2025, I've been getting a new kind of message from people with compromised wallets. It's not the classic "a bot takes my ETH every time I send gas" anymore. Now it's "my wallet has code on it and I never deployed anything".
That's EIP-7702. It's a good upgrade. It lets a normal wallet (an EOA) point at a smart contract and behave like a smart account, which gives you batching, gas sponsorship and all that. But the same feature is a gift for anyone holding a leaked private key, because they can now attach their own sweeper contract to your address. And once that code is on your account, it runs every time someone sends you ETH.
In this guide I'll show you how to check whether your address has a delegation, how to tell a legit one from a malicious one, and how to clear it. I'll also explain why clearing it on its own usually isn't enough.
What a 7702 delegation actually is
EIP-7702 adds a new transaction type, 0x04, called a set-code transaction. Inside it there's a list of authorizations. Each authorization is a tuple signed by the account owner:
[chain_id, address, nonce, y_parity, r, s]
When that transaction is processed, the protocol writes a tiny piece of code to your account: the bytes 0xef0100 followed by the 20-byte address you delegated to. The spec calls this a delegation indicator. From then on, any call to your address executes the code that lives at that delegated address, in the context of your account. Your balance, your storage, your tokens.
Three details from the spec matter a lot when you're dealing with an attacker:
- It's persistent. The delegation stays until another authorization replaces it. It doesn't expire.
- It survives reverts. The spec says the delegation is not rolled back if the rest of the transaction fails.
chain_id0 means every chain. An authorization signed with chain ID 0 is valid on any EVM chain that supports 7702, as long as the nonce matches there.
The spec authors were very aware of the risk. It literally warns that wallets shouldn't let apps prompt users for authorizations, and that a badly built delegate contract can hand an attacker near-complete control of the account.
Why a 7702 sweeper is worse than a normal sweeper
A classic sweeper bot watches the mempool and the chain. When ETH lands in your wallet, it signs a transaction to send it out. That's a race. A fast enough rescue, usually a Flashbots bundle, can win it.
A 7702 sweeper doesn't need to race. If the delegate contract has a receive() function that forwards ETH, the transfer that funds your wallet is the same call that empties it. There's no window. The ETH arrives and leaves inside one execution.
This isn't theoretical. Right after Pectra, Wintermute's research team flagged a family of copy-paste sweeper delegates they nicknamed "CrimeEnjoyor", and CoinDesk covered it. The contracts are basically a receive() that pushes everything to a hardcoded attacker address. They're cheap to deploy and attackers reuse them across thousands of leaked keys.
Step 1: check whether your address is delegated
You don't need any special tool. Just ask a node for the code at your address. With Foundry's cast:
cast code 0xYourAddress --rpc-url https://ethereum-rpc.publicnode.com
Or with raw JSON-RPC:
{"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["0xYourAddress","latest"]}
What the result means:
0xmeans no code, so no delegation. You're a plain EOA.0xef0100followed by 40 hex characters means you're delegated. Those 40 characters are the address of the contract that now controls how your account behaves.
So a result like 0xef0100 + 1111222233334444555566667777888899990000 means calls to your wallet run the code at 0x1111…0000. That address is made up just to show the format.
Block explorers increasingly label delegated EOAs on the address page, but the RPC answer is the source of truth. Do this on every chain you've used that has 7702 enabled, because of the chain ID 0 detail above.
Step 2: is it a delegation you made, or one an attacker made?
Not every delegation is bad. If you turned on a smart-account feature in your wallet, you'll have a delegation to your wallet provider's delegator contract, and that's fine.
Here's how I triage it:
- Did you enable a smart account feature? If not, and there's code on your address, assume compromise.
- Open the delegate address on Etherscan. Is the source verified? Who deployed it? A legit wallet delegator is verified, widely used and documented by the wallet. A sweeper is usually a tiny unverified contract, or a verified one whose
receive()andfallback()forward funds to a fixed address. - Look at the transaction that set it. It's a type-4 transaction. Who sent it? If it was sent by a random address that also funded lots of other victims, you have your answer.
- Watch what happens to incoming ETH. If every incoming transfer leaves in the same transaction, you're dealing with an auto-forwarding delegate.
There are two very different situations here, and the fix depends on which one you're in:
- You signed a malicious authorization, for example on a phishing site, but your private key is still safe. This is the easier case.
- Your private key or seed phrase leaked. The attacker can sign new authorizations whenever they want. This is the hard case.
Step 3: clear the delegation
The spec gives us a clean way out. If you sign an authorization that delegates to the zero address (0x0000000000000000000000000000000000000000), the protocol clears the code and resets your account to the empty code hash. You become a normal EOA again.
If your key is safe and you just signed something bad, this is usually all you need. Many wallets now have an option to switch a smart account back to a standard account, which does exactly this under the hood. Check your wallet's settings first. If yours doesn't, you can do it yourself. Recent versions of Foundry support signing authorizations, for example with cast wallet sign-auth, and sending them with cast send --auth. Check cast --help on your version, because these flags are new and still changing.
One nonce trap catches a lot of people. If the same account both sends the type-4 transaction and signs the authorization, the sender's nonce goes up before the authorizations are processed. So the authorization has to use current nonce + 1, not the current nonce. Get it wrong and the authorization is silently skipped. The transaction succeeds and nothing changes, which is very confusing at 3am.
The cleaner way is to have a different wallet send the transaction. With 7702, the sender (who pays gas) doesn't have to be the account being changed. Your safe wallet pays, and the compromised wallet only provides a signature. That means you don't need any ETH in the compromised wallet at all, which is great, because any ETH you send there gets swept.
Step 4: if the key is leaked, clearing alone won't save you
This is the part people don't want to hear. If the attacker has your key, clearing the delegation buys you nothing on its own. They'll just sign a new one and put the sweeper back, maybe in the very next block. They can also watch for your type-4 transaction and try to get theirs in first.
So with a leaked key, the delegation reset has to happen atomically with the rescue, in one bundle:
- A type-4 transaction sent from your safe wallet, carrying the compromised wallet's authorization to the zero address. This removes the sweeper code. Your safe wallet pays the gas.
- A plain ETH transfer from your safe wallet to the compromised one, just enough for the gas of the next steps. Because the code was cleared one transaction earlier, nothing forwards it away.
- The transfers that move your tokens, NFTs or positions out of the compromised wallet to the safe one.
(The other way is to delegate to a rescue contract you control instead of to zero, and let your safe wallet execute a batch through it. It's more powerful, but you have to trust that contract completely, so I only do this with code I've written or audited.)
You send all of it as a Flashbots bundle so it either lands in one block in exactly that order, or not at all. Nothing hits the public mempool, so the attacker's bot has nothing to react to.
There's an open-source example of this pattern, eth-rescue by mpeyfuss, which clears a 7702 delegation as part of a rescue flow. Read the code before you run anything with a private key in it. That's a general rule: don't paste a compromised key into random tools from a Telegram DM. Half the "rescue services" out there are the second scam.
After the rescue, treat the old address as burned. Don't send anything to it again. Airdrops and vesting unlocks that go to that address are a separate problem, and you'll need a bundle for each one when it happens.
Common mistakes I see
- Sending ETH to "pay for gas" for the clean-up. With an auto-forwarding delegate, that ETH is gone instantly. Sponsor the gas from another wallet instead.
- Only checking mainnet. If the authorization used chain ID 0, the attacker may have delegated you on other chains too.
- Thinking revoking token approvals fixes it. Approvals and delegations are separate things. You should still revoke your token approvals and Permit2 allowances, but that won't remove code from your account.
- Using a public RPC to send the fix. Anything in the public mempool can be seen and countered. Use a private relay or a bundle.
Quick checklist
- Run
eth_getCodeon your address on every chain you use - If it starts with
0xef0100, look up the delegate contract - Key safe: sign an authorization to
0x0(or use your wallet's "switch back" option) - Key leaked: bundle the delegation reset with the asset transfers, sponsored from a safe wallet
- Move everything to a brand-new seed, not just a new account in the same wallet
- Never fund the compromised address again
If you're stuck with a sweeper draining everything you send, the MEVDAO Token Rescue Bot is built for exactly that: it pulls your tokens out of the compromised wallet through Flashbots. It's included with the MEVDAO subscription next to the sniping group and the sniper bot. If your wallet has a 7702 delegation on it, or you've got complicated stuff like staked positions, vesting contracts or airdrops that unlock later, send me a message on Telegram first and we'll look at the delegation together.
And if you want more of this kind of thing every week, join the MEV Secrets email list right below.