DEV Community

Semantic-Sentry
Semantic-Sentry

Posted on

EIP-7702 in practice: testing three browser extension wallets

EIP-7702 shipped with Ethereum's Pectra upgrade. It lets an EOA
delegate its code to a smart contract via an authorization_list
in a type-4 transaction. If a user signs an authorization to
an attacker-controlled delegate, the attacker gains full control
over the EOA — all tokens, NFTs, staking positions, and approvals.

The security model depends entirely on the wallet. And most of the
writing about 7702 falls into two camps: hype ("this changes
everything") or speculation ("wallets might not handle this").
Nobody, as far as I could find, had actually tested what the
major extension wallets do when a dApp throws a type-4 transaction
at them.

So I did.

This is a negative finding. I didn't find a bug. But I did find
that the three most-used browser extension wallets each handle
EIP-7702 differently — and that the current attack surface is
effectively closed on extensions. Here's the data.

Methodology

I set up a local Anvil node with --hardfork prague --chain-id 31337
and a minimal dApp served over HTTP to Chrome. The dApp has no
access to the user's private key and can only interact via the
injected window.ethereum provider.

The "victim" is Anvil account #0
(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266), whose private key is
publicly known from Foundry documentation. This is intentional —
it removes "did the attacker have the key?" as a variable. Every
delegation attempt uses this address as authority.

I tested three vectors against each wallet:

  1. eth_sendTransaction with an authorizationList field (baseline and non-empty variants)
  2. eth_sign on a computed authorization hash: keccak256(0x05 || rlp([chain_id, address, nonce]))
  3. wallet_signAuthorization — the RPC method specified in the 7702 spec for wallets to sign authorization tuples on behalf of the user

The goal for each: determine whether a malicious dApp can obtain
a valid authorization from a user without the user understanding
what they are signing.

Results

MetaMask Extension 13.47.0

Vector 1 (eth_sendTransaction type-4):
Error returned to the dApp: "External EIP-7702 transactions are
not supported." MetaMask recognizes type-4 and rejects it before
signing. This aligns with the "Added Protection" feature they
shipped in September 2026.

Vector 2 (eth_sign on auth hash):
MetaMask shows a warning on eth_sign — this is well-documented
behavior on recent versions.

Vector 3 (wallet_signAuthorization):
{ "code": -32601, "message": "method not found" }

Verdict: MetaMask has explicitly closed the surface. The wallet
will not sign 7702 authorizations from dApps.

Trust Wallet Extension

Vector 1 (eth_sendTransaction type-4):
No error surfaced to the dApp. On-chain receipt shows type: 0,
gasUsed: 21000, code: 0x. The wallet silently downgraded the
type-4 transaction to a type-0 transaction and stripped the
authorizationList before broadcasting.

Verdict: Safe degradation. The user gets the same simple transfer
they would have gotten without 7702 fields. No delegation applied,
no funds at risk.

The tradeoff: the wallet changed the transaction type without
telling the user. That's arguably a UX issue, but it's not a
security issue — the user's intent (send X to Y) is preserved,
and nothing extra happens.

Rabby Extension

Vector 1: Not tested directly (skipped in favor of the other two).

Vector 2 (eth_sign on auth hash):
Rabby shows a dialog: "Signing with 'eth_sign' can lead to loss
of assets. For your safety, Rabby does not support this method."

If the user dismisses that and proceeds, the confirmation screen
shows: "Unknown signature type" with the raw hex payload.

Verdict: Correct behavior. Rabby flags both the method and the
payload. A user who reads the warnings and still signs is making
an informed decision.

Vector 3 (wallet_signAuthorization):
{ "code": -32601, "message": "method not found" }

What this means

Two independent conclusions:

First, on extensions: the attack surface is closed. Three wallets,
three different protection mechanisms (refusal, degradation,
warning), same result — no dApp can obtain a valid 7702
authorization through a user. This is a good outcome for users,
and it's a direct consequence of the vendors having thought
about this before Pectra went live.

Second, on infrastructure: the entire class of EIP-7702 integrations
that assume wallet_signAuthorization is available currently has
no place to land. Account abstraction SDKs that help users
"upgrade" their EOA to a smart account cannot actually do so via
extensions today.

A side note on AA SDKs

While researching this, I noticed something worth flagging for
the future.

The ZeroDev SDK's createKernelAccount accepts accountImplementationAddress
and factoryAddress as parameters without validating them against
a known-allowlist (packages/core/accounts/kernel/createKernelAccount.ts,
lines 135-137 and 367-371).

This is not exploitable today. ZeroDev can't sign authorizations
itself — it must call wallet_signAuthorization on the user's wallet,
and no extension wallet implements that method. A malicious dApp
cannot deliver a valid authorization to the SDK, so the parameter
is never reached.

But it will matter. When a wallet adds wallet_signAuthorization
support, this code path becomes reachable. At that point, whether
it's a vulnerability depends entirely on the wallet's UI: if the
confirmation screen shows the delegate address, the SDK's
parameter is still safe. If the wallet doesn't show it, the SDK
parameter becomes a real vector.

I've documented this as a "future risk" finding rather than a
current vulnerability. It's an early warning for both ZeroDev
(to add an allowlist) and wallet vendors (to render delegations
in the UI).

What's next

The extension surface is closed. The remaining surfaces are:

  • Mobile wallets: different codebases than extensions, may lag behind on protections.
  • AA SDKs, once wallet_signAuthorization becomes available in consumer wallets.
  • On-chain consumers of EIP-7702 in smart contracts — but that's a much broader topic.

If you maintain a wallet or an AA SDK and want to talk about
this, my contact info is in the repo.

Artifacts

Everything is open source:
github.com/Semantic-Sentry/eip7702-wallet-research

Includes:

  • encoder.py — working EIP-7702 type-4 transaction encoder
  • sponsoring_test.py — sponsoring pattern test (sender ≠ authority)
  • wallet_harness.html — dApp harness for testing wallet rendering
  • FINDINGS.md — full methodology and raw results

MIT licensed. Use it, fork it, improve it.

Thanks to the teams at MetaMask, Trust Wallet, and Rabby for
building protections into their products before users needed them.

Top comments (1)

Collapse
 
bloqarl profile image
Carlos (Bloqarl) •

Really like that you published a negative result, we don't see enough of those. Testing what wallets actually do beats another thread of speculation.

From the contract side, what I'd watch is less the signing prompt and more what happens after: delegates with an init call someone else can front-run, storage left behind when a user re-delegates to a different implementation, and old msg.sender == tx.origin checks that assumed EOAs have no code. Are you planning mobile wallets next? That's where I'd expect the differences.