# How EIP-7702 works

> Understanding how Wallet APIs use EIP-7702

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

[EIP-7702](https://eips.ethereum.org/EIPS/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.

## How it works

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](/docs/wallets/transactions/send-transactions) guide.

## How to use non-7702 mode

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.

<Note>
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.
</Note>

**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

<Tabs>
  <Tab title="SDK">
    ```ts
    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: [...],
    });
    ```
  </Tab>

  <Tab title="API">
    ```bash
    # First, request a Smart Contract Account
    ACCOUNT_ADDRESS=$(curl --request POST \
      --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
      --header 'accept: application/json' \
      --data '{
        "id": 1,
        "jsonrpc": "2.0",
        "method": "wallet_requestAccount",
        "params": [{ "signerAddress": "'$SIGNER_ADDRESS'", "creationHint": { "accountType": "sma-b" } }]
      }' | jq -r '.result.accountAddress')

    # Use the SCA address (not the signer address) in subsequent calls
    curl --request POST \
      --url https://api.g.alchemy.com/v2/$ALCHEMY_API_KEY \
      --header 'accept: application/json' \
      --data '{
        "id": 1,
        "jsonrpc": "2.0",
        "method": "wallet_prepareCalls",
        "params": [{
          "calls": [{ "to": "0x...", "data": "0x" }],
          "from": "'$ACCOUNT_ADDRESS'",
          "chainId": "'$CHAIN_ID'"
        }]
      }'
    ```
  </Tab>
</Tabs>

## Advanced

<Accordion title="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.
</Accordion>

<Accordion title="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:

  * [Viem](https://viem.sh/docs/eip7702/signAuthorization)
</Accordion>

<Accordion title="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.
</Accordion>

<Accordion title="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.
</Accordion>

<Accordion title="EIP-7702 delegations">
  EIP-7702 delegation is now the default mode for Wallet APIs. 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](https://eips.ethereum.org/EIPS/eip-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](https://eips.ethereum.org/EIPS/eip-7702#behavior).
</Accordion>

<Accordion title="Un-delegating accounts">
  To remove a delegation and return an account to a pure EOA, you must **re-delegate to the zero address**:
  `0x0000000000000000000000000000000000000000`.

  **Enterprise customers** can use sponsored undelegation via the SDK or API — see the [Undelegate account](/docs/wallets/transactions/undelegate-account) guide.

  **Non-enterprise customers** can submit the undelegation manually by sending the transaction directly from the account:

  1. Fund the account with a native gas token to cover gas fees.
  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](https://viem.sh/docs/eip7702/signAuthorization).
</Accordion>

<Accordion title="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:

```ts title="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](/docs/wallets/transactions/using-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](/docs/wallets/resources/migration-v5) for a complete cheat sheet.
</Accordion>


## Next steps

Build more:

* [Sponsor gas](/docs/wallets/transactions/sponsor-gas)