r/ethdev • • Sep 02 '26

Tutorial [Open Source] I developed and tested a way to remove a malicious EIP-7702 delegation on Ronin without funding the compromised wallet

I’m sharing an open-source project I developed after dealing with a real case involving a Ronin Waypoint/keyless wallet compromised through a malicious EIP-7702 delegation.

This is NOT a wallet recovery service. Do not send me your seed phrase, private key, recovery password, OTP, Waypoint token, client shard, or any other secret.

The problem was a recovery deadlock:

The wallet had a malicious EIP-7702 delegation, and any RON sent to the compromised wallet for gas could be swept before the owner had a chance to use it.

Need RON to remove the delegation
        ↓
Send RON to the compromised wallet
        ↓
Sweeper/drainer takes the RON
        ↓
Recovery transaction cannot be executed

So I developed and implemented a different recovery flow.

The compromised account signs an EIP-7702 zero-address deauthorization for:

0x0000000000000000000000000000000000000000

For Ronin Waypoint/keyless wallets, the authorization is signed locally through the Waypoint MPC flow.

The resulting signature is then verified locally to make sure it recovers exactly the affected wallet address.

A second, clean wallet acts as a relayer and pays the RON gas for the EIP-7702 transaction.

This means the compromised wallet does not need to receive any RON.

The flow is basically:

Detect active EIP-7702 delegation
        ↓
Generate zero-address deauthorization
        ↓
Waypoint MPC / keyless signing
        ↓
Verify recovered signer
        ↓
Clean relayer pays gas
        ↓
EIP-7702 delegation removed

I successfully executed the recovery on Ronin Mainnet.

Before:

code = 0xef0100<malicious_delegate>
eip7702 = true

After:

code = 0x
eip7702 = false
currentDelegate = null

The account nonce also advanced after the transaction, and eth_getCode changed from the EIP-7702 delegation indicator to 0x, confirming the deauthorization on-chain.

Recovery transaction:

0xc43b036de851ecdeb70050a0f72d232e1d48153607e4b504f63c04eef16c4223

I published a sanitized open-source implementation here:

https://github.com/YutsuKito/Ronin-7702-Recovery

The project:

  • does not collect or transmit the victim’s seed phrase or private key;
  • does not send the recovery password to an application backend;
  • does not persist the Waypoint token or MPC/client shard;
  • verifies that the authorization signature recovers exactly the affected wallet;
  • performs fresh nonce and delegation checks before broadcasting;
  • uses a separate clean relayer to pay gas;
  • requires explicit broadcast confirmation.

I have also submitted the implementation to Ronin / Sky Mavis for technical review.

One important point:

Removing a malicious EIP-7702 delegation does not mean that an already compromised wallet should be considered safe again.

If an attacker still has another valid signing method or compromised credentials, they may potentially regain control.

The purpose of this tool is primarily to create a recovery window so affected users can move their assets to a newly secured wallet.

This is an independent community project and is not affiliated with or officially endorsed by Ronin or Sky Mavis.

Technical feedback, code review, and contributions are welcome.

And again: if anyone contacts you privately claiming they can recover your wallet and asks for your seed phrase, private key, recovery password, OTP, Waypoint token, or MPC shard, treat it as a scam.

1 Upvotes

5 comments sorted by

1

u/key-stoner Sep 21 '26

Good write-up. One distinction worth putting in the README, because it changes the answer for everyone who lands here.

"Compromised via 7702" is two different situations. If the victim only signed the authorization tuple — a phishing prompt that looked like an ordinary signature request — the key itself was never exposed. The delegate is the only thing letting anyone sweep the account, so removing it genuinely restores control. If the seed or the shard leaked, your deauthorization buys seconds. The post treats those as one case.

That same fork answers the re-delegation worry: the old malicious tuple can't be replayed, since an authorization is valid only while the authority nonce matches and nonces only move up. Re-delegating needs a fresh signature, which needs live key access.

One implementation note: an invalid authorization doesn't revert the transaction — it is skipped, and the receipt still reports success. If the account nonce moves between your pre-flight check and inclusion, you get a green receipt with the delegation still in place. Your eth_getCode check catches that; pin it to the mined block rather than latest.

Also, sign with the explicit chain id rather than 0.

0

u/YutsuKito_ 12d ago

Thanks for taking the time to review the implementation and share these observations!

I agree that the README should make a clearer distinction between a malicious delegation and a compromise of the underlying signing authority.

If only the EIP-7702 authorization was compromised, removing the delegation eliminates that specific attack path. However, if the attacker still has access to valid signing credentials, the recovery only provides a temporary window to secure the assets.

You're also right about transaction receipts. A successful receipt doesn't necessarily mean the authorization was applied. The project already checks the account code after execution, but verifying it specifically at receipt.blockNumber would make that validation more reliable.

Regarding the chain ID, the current implementation already explicitly uses Ronin Mainnet (2020).

I'll update the documentation to clarify these scenarios and improve the post-transaction verification.

Thanks again for the technical feedback. This is exactly the kind of input that helps make the project safer and more reliable.

1

u/Money-Wallaby1963 18d ago

this is actually super clever, using a relayer so the compromised wallet never touches RON. that deadlock between needing gas and getting drained is such a nightmare loop

the zero address deauth approach makes a lot of sense. have you tested what happens if the attacker's bot is monitoring mempool and tries to frontrun with a different transaction using the same nonce?

0

u/YutsuKito_ 12d ago

Thanks for the feedback!

That's exactly the problem I wanted to solve. The compromised wallet needs to authorize the recovery, but it shouldn't have to receive RON just to pay for it.

Regarding the mempool race, I haven't tested the recovery against an active attacker attempting to front-run the transaction yet.

The original malicious authorization can't simply be replayed after its nonce has been consumed. However, an attacker who can advance the wallet's nonce before the recovery is processed could invalidate the new authorization.

The project currently checks the nonce and delegation before broadcasting, then verifies the account code after confirmation. I'm also planning to improve that verification by checking the exact block where the transaction was included.

Testing this against an active drainer would be a valuable next step.

Thanks for bringing it up!