Skip to content
Alchemy Logo

How EIP-7702 works

EIP-7702 is enabled by default, giving you access to all Smart Wallet capabilities including gas sponsorship, batching, and more - while keeping the same address.

EIP-7702 enables EOAs (Externally Owned Accounts) to delegate to a smart wallet that can execute code directly from their addresses. When using Transaction APIs:

  • Use your owner address directly as the account address - no need to call wallet_requestAccount first
  • Transaction APIs automatically detect whether delegation via EIP-7702 is needed
  • If delegation is required, Transaction APIs prepare the correct authorization payload
  • Your application prompts for signing when required
  • The delegation and transaction are combined into a single onchain submission

Once delegated, the account behaves as a Smart Wallet while keeping the same address and assets. Subsequent transactions require only a single signature.

For implementation details, see the Send Transactions guide.

If you need to use a traditional wallet instead of EIP-7702, opt out of the default 7702 behavior by calling wallet_requestAccount first.

When you call wallet_requestAccount with an owner address, it creates a dedicated smart wallet address. Using this address (instead of your owner address) in subsequent API calls bypasses 7702 mode.

If you've already used an owner address in 7702 mode (e.g. by calling wallet_prepareCalls with the owner address), specify creationHint: { accountType: "sma-b" } when calling wallet_requestAccount to create a separate smart wallet for that owner.

When to use non-7702 mode:

  • Backwards compatibility with existing wallets
  • Using chains that don't yet support EIP-7702
  • Using an owner that doesn't support signing EIP-7702 authorizations
  • Specific requirements for smart wallet architecture
import type { Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";
 
const client = createSmartWalletClient({
  transport: alchemyWalletTransport({ apiKey: "YOUR_API_KEY" }),
  chain: sepolia,
  signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
});
 
// Request a Smart Contract Account
const { address } = await client.requestAccount({ creationHint: { accountType: "sma-b" } });
 
// Pass the SCA address as the account to use non-7702 mode
await client.sendCalls({
  account: address,
  calls: [...],
});

How Wallet APIs handle delegation and signing

When interacting with Wallet APIs, delegation is handled automatically as part of transaction preparation.

If delegation has not yet occurred on the target chain, the API response includes multiple signature requests:

  1. An EIP-7702 authorization signature (for delegation)
  2. A transaction signature (for the transaction itself)

Your application is responsible for:

  • Prompting for each signature
  • Returning the signatures

These signatures are combined into a single transaction and submitted. After delegation is completed, future requests require only a transaction signature.

EIP-7702 authorization signing

When delegation is required, Wallet APIs return a Prepared EIP-7702 Authorization object.

This includes:

  • The delegation contract address
  • A nonce
  • The chain ID
  • A signatureRequest describing how the authorization must be signed

For quick testing, use eth_sign to sign the signatureRequest.rawPayload.

For production usage:

  • Verifying the delegation address is trusted
  • Using a dedicated EIP-7702 signing utility to compute the hash to sign

Example of signing utility:

Delegation-only (smart wallet upgrade) flows

You do not need to send a dummy or no-op transaction to perform delegation.

If an account needs to upgrade to a smart wallet:

  • Call wallet_prepareCalls with your intended calls (or an empty call set)
  • Wallet APIs detect that delegation is required
  • The response includes the required authorization and transaction signature requests

Combining delegation with the transaction is handled automatically.

Wallet compatibility considerations

Some wallets restrict or block signing EIP-7702 authorizations for security reasons.

In particular:

  • MetaMask only allows delegation to its own contract via its UI
  • MetaMask does not support signing arbitrary EIP-7702 authorization payloads

For MetaMask users, you may need to rely on wallet-native features such as ERC-5792 batching instead of direct EIP-7702 delegation flows.

Ensure the target wallets support EIP-7702 authorization signing before enabling this flow.

EIP-7702 delegations

EIP-7702 delegation is now the default mode for Smart Wallets. When you use your owner address directly with wallet_prepareCalls or other Transaction APIs, 7702 mode is automatically enabled.

The eip7702Auth capability supports the interface defined in ERC-7902.

Currently, Wallet APIs only support delegation to the following contract: 0x69007702764179f14F51cdce752f4f775d74E139 (Modular Account v2)

All other delegation addresses will be rejected.

Once delegated, an account remains delegated until the delegation is replaced or removed.

To reset an account back to a pure EOA, delegate to 0x0000000000000000000000000000000000000000 as defined in EIP-7702.

Un-delegating accounts

To remove a delegation and return an account to a pure EOA, you must re-delegate to the zero address: 0x0000000000000000000000000000000000000000.

Undelegations cannot be relayed, so you must submit this transaction directly from the account (with enough native gas token to cover fees). If you are re-delegating to another smart wallet, the transaction can be relayed.

To undelegate:

  1. Fund the account with a native gas token.
  2. Sign an EIP-7702 authorization delegating to address(0) with currentNonce + 1.
  3. Send an empty transaction (using currentNonce) that includes the authorization.

Use Viem to sign the EIP-7702 authorization (with executor: self): Viem signAuthorization.

Using @account-kit/wallet-client (v4.x.x)?

The examples on this page use @alchemy/wallet-apis (v5.x.x). If you're using @account-kit/wallet-client (v4.x.x), the client setup looks like this:

client.ts (v4.x.x)
import { LocalAccountSigner } from "@aa-sdk/core";
import { createSmartWalletClient } from "@account-kit/wallet-client";
import { alchemy, sepolia } from "@account-kit/infra";
 
const signer = LocalAccountSigner.privateKeyToAccountSigner("0xYOUR_PRIVATE_KEY" as const);
 
export const client = createSmartWalletClient({
  transport: alchemy({ apiKey: "YOUR_API_KEY" }),
  chain: sepolia,
  signer,
  account: signer.address, // can also be passed per action as `from` or `account`
  // Optional: sponsor gas for your users (see "Sponsor gas" guide)
  policyId: "YOUR_POLICY_ID", 
});

Key v4.x.x differences:

  • Account address must be specified on the client or per action (from or account). In v5.x.x, the client automatically uses the owner's address as the account address via EIP-7702.
  • Chain imports come directly from @account-kit/infra instead of viem/chains.
  • Numeric values use hex strings: value: "0x0" instead of value: BigInt(0).
  • In v4.x.x, the paymaster capability on prepareCalls or sendCalls is called paymasterService instead of paymaster, or you can set the policyId directly on the client.
  • Owners use LocalAccountSigner / WalletClientSigner from @aa-sdk/core. In v5.x.x, a viem LocalAccount or WalletClient is used directly.

See the full migration guide for a complete cheat sheet.

Build more:

Was this page helpful?