NextTech Insights
EIP-7702 delegation: how to check if your wallet is delegated and how to revoke it
web3securityeip-7702

EIP-7702 delegation: how to check if your wallet is delegated and how to revoke it

DigitalCraft
9 min read

Check whether your Ethereum EOA has an EIP-7702 delegation with one eth_getCode call, decide whether the target is safe, and reset it by authorizing the zero address. Includes a dependency-free checker, a tested viem revoke snippet, and a 600-block mainnet sample.

Table of Contents

How do you check whether your wallet has an EIP-7702 delegation, and how do you remove it?

Call eth_getCode on your address. If it returns 0x, the account has no delegation. If it returns 23 bytes starting with 0xef0100, the account is delegated, and the remaining 20 bytes are the contract that now runs whenever someone calls your address. To remove the delegation, send a type-4 transaction with an authorization for the zero address, or use your wallet's "switch back to standard account" setting. Removal resets the code to empty. It does not move funds, revoke token approvals, or help if your private key has leaked.

This guide is for anyone who saw an unfamiliar "smart account" or "delegation" prompt, found a "Delegated to" label on a block explorer, or wants to audit their own EOAs after Ethereum's Pectra upgrade.

What a delegation is, in one paragraph

EIP-7702 (Final, activated on Ethereum mainnet with Pectra in May 2025) adds a transaction type, 0x04, that carries an authorization_list. Each entry is [chain_id, address, nonce, y_parity, r, s], signed by the EOA over keccak(0x05 || rlp([chain_id, address, nonce])). When a valid authorization is processed, the EOA's code becomes the delegation indicator 0xef0100 || address. From then on, any call to your EOA executes the delegate contract's code in the context of your account, with your balance and your storage. The spec puts it bluntly: the delegated code "has unrestricted access to the account". The delegation stays in place until another authorization replaces or clears it. There is no expiry.

Three details matter for auditing:

  • It is per chain. An authorization with your chain's ID only applies there. chain_id = 0 makes it valid on every EVM chain that supports 7702, so check each network you use.
  • The private key still works. Your EOA can still sign ordinary transactions, so a delegation adds capabilities; it never locks you out.
  • Clearing is built in. An authorization for 0x0000000000000000000000000000000000000000 resets the account's code hash to empty instead of writing an indicator.

Step 1: Check the code at your address

Any JSON-RPC endpoint can answer this. The script below has no dependencies (Node.js 18+ for fetch) and makes read-only calls; it never asks for a key.

// check-7702.mjs
// Usage: node check-7702.mjs <address> [rpcUrl]
const [address, rpc = 'https://ethereum-rpc.publicnode.com'] = process.argv.slice(2);
if (!/^0x[0-9a-fA-F]{40}$/.test(address ?? '')) {
  console.error('usage: node check-7702.mjs <0x address> [rpcUrl]');
  process.exit(1);
}

async function rpcCall(method, params) {
  const res = await fetch(rpc, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
  });
  const json = await res.json();
  if (json.error) throw new Error(json.error.message);
  return json.result;
}

const [code, chainId] = await Promise.all([
  rpcCall('eth_getCode', [address, 'latest']),
  rpcCall('eth_chainId', []),
]);

const hex = code.toLowerCase();
if (hex === '0x') {
  console.log(`chain ${Number(chainId)}: ${address} has no code (plain EOA, no delegation)`);
} else if (hex.startsWith('0xef0100') && hex.length === 2 + 46) {
  console.log(`chain ${Number(chainId)}: ${address} is DELEGATED to 0x${hex.slice(8)}`);
} else {
  console.log(
    `chain ${Number(chainId)}: ${address} is a contract (${(hex.length - 2) / 2} bytes of code)`
  );
}

We ran it on mainnet on 2026-10-13. The three possible results look like this. The two EOA addresses are redacted; the contract is USDC, used as a known non-EOA example:

chain 1: 0x…(your EOA) has no code (plain EOA, no delegation)
chain 1: 0x…(a delegated EOA) is DELEGATED to 0x5a7fc11397e9a8ad41bf10bf13f22b0a63f96f6d
chain 1: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 is a contract (2186 bytes of code)

Run it once per chain by passing that chain's RPC URL as the second argument. A block explorer's address page shows the same information, but the raw eth_getCode result is the ground truth and works on chains where your explorer has no 7702 label yet.

Step 2: Decide whether the delegation is expected

Being delegated is not a problem in itself. Wallets such as MetaMask now upgrade accounts to "smart accounts" through 7702, and MetaMask enables this automatically for new users. What matters is whether you recognize the target and why it is there.

| What you find | Likely cause | What to do | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | 0x on every chain you use | No delegation | Nothing. Re-check after any unfamiliar signing prompt. | | Delegated to your wallet vendor's documented delegator (for example MetaMask's EIP7702StatelessDeleGator, labeled "MetaMask: EIP-7702 Delegator" on Etherscan) | You or your wallet enabled smart-account features | Keep it if you use batching or gas sponsorship. Otherwise switch back to standard to shrink the attack surface. | | Delegated to a contract you cannot identify, or one with no verified source | You signed an authorization from a dapp, link, or "upgrade" page | Treat it as hostile. Move assets to a fresh wallet first, then clear the delegation (Step 3). | | Delegated to a known sweeper contract, or funds leave seconds after arriving | Your private key or seed phrase has leaked | Clearing will not save this wallet: the attacker can sign a new authorization at any time. Abandon the key and move anything that can still be rescued. | | Delegated on a chain you never used | You signed an authorization with chain_id = 0, which is valid on every chain where your nonce matches | Clear it on that chain too, and find where you signed it. |

Two incidents show why the third and fourth rows are different problems:

  • Leaked keys + sweepers. In June 2025, Wintermute reported that more than 80% of 7702 delegations at the time pointed to copy-pasted "sweeper" contracts that drain any ETH sent to wallets whose keys were already compromised. The delegation was a symptom; the leaked key was the cause.
  • Phishing a legitimate delegator. On 2025-05-24 a MetaMask user lost about $146,000. The account was delegated to MetaMask's legitimate delegator, and the attacker got the victim to sign one batched transaction that bundled token approvals and transfers. Clearing the delegation would not have helped after the fact; reading the batch before signing would have.

The EIP itself warns wallet builders that applications "must not" expect to ask users to sign authorizations, because there is no safe generic interface for it. A dapp that asks you to sign a 7702 authorization directly, especially through a link in an email or DM, is a red flag on its own.

Step 3: Clear the delegation

Option A: Use your wallet's setting

If your wallet created the delegation, use its own switch. In MetaMask (extension), open the account menu, choose Account details → Smart account, turn the toggle off for each network, and confirm the transaction. Mobile has the same toggle under Smart account. Each network is a separate on-chain transaction with its own gas fee.

Option B: Send the zero-address authorization yourself

For wallets without a toggle, or if you are scripting cleanup for accounts you control, sign an authorization for the zero address and send it in a type-4 transaction. With viem 2.x:

import { createWalletClient, http, zeroAddress } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

const account = privateKeyToAccount(process.env.PRIVATE_KEY); // the delegated EOA
const client = createWalletClient({
  account,
  chain: mainnet,
  transport: http(process.env.RPC_URL),
});

// The EOA sends the transaction itself, so the authorization nonce must be current nonce + 1.
const authorization = await client.signAuthorization({
  contractAddress: zeroAddress,
  executor: 'self',
});

const hash = await client.sendTransaction({
  authorizationList: [authorization],
  to: account.address,
  data: '0x',
});
console.log(hash);

The executor: 'self' flag matters. The spec increments the sender's nonce before processing the authorization list, so an authorization signed with the current nonce is silently skipped when the same EOA sends the transaction. We verified the signing half offline with a fresh throwaway key whose on-chain nonce was 0:

{ chainId: 1, address: '0x0000000000000000000000000000000000000000', nonce: 1 }
hash    0x397fc2d6f03e1be9ab7ff9b87528f3363ef0163fe3b36f42f5065980b6f357b3
signer ok: true

viem set the nonce to 1, not 0, and recoverAuthorizationAddress returned the throwaway account. We did not broadcast the transaction: the key was never funded. Test the full flow on Sepolia before you run it against a mainnet account.

If someone else pays the gas (a relayer or a second wallet you control), drop executor: 'self'. The authorization nonce is then the EOA's current nonce.

Step 4: Verify the reset, then finish the cleanup

  1. Run check-7702.mjs again on every chain. You want has no code.
  2. Review token approvals separately. A delegation and an ERC-20 allowance are independent: clearing one does nothing to the other.
  3. If any row in Step 2 pointed to a leaked key, do not reuse the address, even after the reset.

Changing a delegation does not clear the account's storage. EIP-7702 notes that wiping storage is not a protocol operation, so leftover state from one delegate can still be read by the next one. This is mostly a concern for developers who switch between delegate implementations; a "stateless" delegator design avoids it.

What we saw on mainnet (original sample)

To see how common delegations and resets are in practice, we scanned 600 consecutive mainnet blocks (26,179,309 to 26,179,908, ending 2026-10-13 00:13 UTC) with plain eth_getBlockByNumber calls.

| Metric | Value | | ------------------------------------ | ------------------ | | Transactions scanned | 150,974 | | Type-4 (set code) transactions | 1,875 (1.2%) | | Authorization tuples included | 2,963 | | Distinct delegate targets | 73 | | Share of the most common target | 959 tuples (32.4%) | | MetaMask EIP7702StatelessDeleGator | 164 tuples (5.5%) | | Zero-address resets | 83 tuples (2.8%) | | chain_id = 0 authorizations | 0 |

These counts cover authorizations included in blocks, not ones the EVM accepted; an invalid tuple is skipped without reverting the transaction. They are a one-hour snapshot, not a trend. Two observations still hold: delegation is routine traffic now, and resets happen in meaningful numbers, so the zero-address path is well exercised by wallets in production.

Sources

Disclaimer

Not financial advice. General security guidance only. Wallet interfaces, delegator contracts, and chain support for EIP-7702 change frequently. Verify current behavior for your wallet and network, and test scripts on a testnet before using them with real funds.

Popular

  1. 1Permit2 explained (Web3): why approvals changed and how to use it safely (checklist)
  2. 2Read wallet signing screens (Web3): a 30-second checklist to avoid permission traps
  3. 3Spec-to-implementation prompt template (AI development): how to stop the model from guessing
  4. 4Revoke token approvals on EVM: how to audit allowances safely (checklist)
  5. 5Clarifying questions checklist (AI development): what to ask before you let an LLM build

Related Articles