> ## Documentation Index
> Fetch the complete documentation index at: https://docs.startale.com/llms.txt
> Use this file to discover all available pages before exploring further.

# EIP-7702 developer guide

> Upgrade an existing EOA into a Startale Smart Account by delegating it to the Startale account implementation.

[EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) lets an existing EOA delegate execution to a smart contract while keeping the **same address**. Combined with the Startale Smart Account, that means you can take any EOA and start sending UserOperations from it without migrating funds, rotating keys, or asking the user to remember a new address.

<Note>
  Source: [`StartaleGroup/scs-aa-sdk`](https://github.com/StartaleGroup/scs-aa-sdk).
</Note>

## What EIP-7702 does, in one diagram

```mermaid theme={null}
flowchart LR
  subgraph "Before"
    EOA1["EOA address<br/>code = empty"]
  end
  subgraph "After delegation"
    EOA2["Same EOA address<br/>code = 0xef0100 || implementation"]
    Impl["Startale account<br/>implementation"]
    EOA2 -.delegated.-> Impl
  end
  EOA1 -->|signAuthorization| EOA2
```

The address is unchanged. What changes is the code at that address: a 23-byte **delegation indicator** (`0xef0100 || implementation`) that tells the EVM to execute the implementation's code whenever the address is called. To revert, the user signs a new authorization that points at the zero address.

## Why use it

| Benefit                      | Detail                                                                                        |
| ---------------------------- | --------------------------------------------------------------------------------------------- |
| **No address change**        | Funds, allowances, and onchain history follow the user.                                       |
| **No deploy step**           | Authorization is included in a transaction; the EVM applies the delegation at execution time. |
| **All AA features unlocked** | Sponsored gas, ERC-20 gas, sessions, recovery, and batched calls become available on an EOA.  |
| **Reversible**               | Authorization for `0x0` clears the delegation.                                                |

## Prerequisites

* A signer for the EOA you want to upgrade (private key, wallet client, EIP-1193 provider, or ethers wallet).
* The Startale account `implementationAddress` (see [Contracts and audits](/aa-sdk/resources/contracts-and-audits)).
* The bundler and paymaster URLs from the [SCS Portal](/aa-sdk/tutorials/portal).

```bash theme={null}
npm install @startale-scs/aa-sdk viem
```

## Path A: automatic authorization (recommended)

When you pass `eip7702Account` to `toStartaleSmartAccount`, the SDK signs the authorization for you on the next UserOperation. This is the cleanest integration: the user signs once, the delegation is applied as part of the same UserOp, and you keep using the same `StartaleAccountClient` afterwards.

```ts theme={null}
import { http, createPublicClient } from "viem"
import { privateKeyToAccount } from "viem/accounts"
import { soneiumMinato } from "viem/chains"
import {
  createSCSPaymasterClient,
  createSmartAccountClient,
  toStartaleSmartAccount,
} from "@startale-scs/aa-sdk"

const signer = privateKeyToAccount(process.env.OWNER_PRIVATE_KEY as `0x${string}`)
const eoaAddress = signer.address

const publicClient = createPublicClient({ chain: soneiumMinato, transport: http() })

const paymasterClient = createSCSPaymasterClient({
  transport: http(process.env.PAYMASTER_URL!),
})

const smartAccountClient = createSmartAccountClient({
  account: await toStartaleSmartAccount({
    signer,
    chain: soneiumMinato,
    transport: http(),
    accountAddress: eoaAddress,
    eip7702Account: signer,
  }),
  transport: http(process.env.BUNDLER_URL!),
  client: publicClient,
  paymaster: paymasterClient,
  paymasterContext: {
    paymasterId: process.env.PAYMASTER_ID!,
  },
})
```

| Symbol                         | Source                             | Role                                                                                      |
| ------------------------------ | ---------------------------------- | ----------------------------------------------------------------------------------------- |
| `privateKeyToAccount`          | `viem/accounts`                    | Builds a viem `LocalAccount` for the EOA.                                                 |
| `accountAddress`               | `toStartaleSmartAccount` parameter | Pins the smart account to the EOA's address instead of deriving a new counterfactual one. |
| `eip7702Account`               | `toStartaleSmartAccount` parameter | When set, the SDK uses this signer to sign the EIP-7702 authorization on the next UserOp. |
| `paymasterContext.paymasterId` | request flag                       | Optional. Sponsoring the upgrade UserOp removes the need for the EOA to hold ETH.         |

## Path B: manual authorization

If you need to inspect or persist the authorization yourself (for example, to store it server-side), sign it explicitly with a viem `WalletClient` and pass the result as `eip7702Auth`.

```ts theme={null}
import { createWalletClient, http } from "viem"
import { soneiumMinato } from "viem/chains"
import { toStartaleSmartAccount } from "@startale-scs/aa-sdk"

const walletClient = createWalletClient({
  account: signer,
  chain: soneiumMinato,
  transport: http(),
})

const authorization = await walletClient.signAuthorization({
  contractAddress: process.env.STARTALE_ACCOUNT_IMPLEMENTATION_ADDRESS as `0x${string}`,
})

const account = await toStartaleSmartAccount({
  signer,
  chain: soneiumMinato,
  transport: http(),
  accountAddress: signer.address,
  eip7702Auth: authorization,
})
```

| Symbol                           | Source                             | Role                                                                             |
| -------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------- |
| `walletClient.signAuthorization` | `viem`                             | Returns a `SignAuthorizationReturnType` over `{ chainId, address, nonce, ... }`. |
| `eip7702Auth`                    | `toStartaleSmartAccount` parameter | A pre-signed authorization to attach to the next UserOp.                         |

Use Path B when you want to:

* Prepare authorizations server-side and ship them to the client.
* Sign once with a hardware-backed wallet and reuse the result.
* Inspect the structure of the authorization before submitting it.

## Send a UserOperation

After either path, the client behaves like any other Startale account client:

```ts theme={null}
const hash = await smartAccountClient.sendUserOperation({
  calls: [{ to: target, data: callData, value: 0n }],
})
const receipt = await smartAccountClient.waitForUserOperationReceipt({ hash })
```

The first UserOp also lands the EIP-7702 delegation; subsequent ones simply use it.

## Inspect and revert

The smart account exposes EIP-7702 helpers directly:

```ts theme={null}
const isDelegated = await smartAccountClient.account.isDelegated()

if (isDelegated) {
  const tx = await smartAccountClient.account.unDelegate()
  await publicClient.waitForTransactionReceipt({ hash: tx })
}
```

| Method                  | Source                 | Role                                                                    |
| ----------------------- | ---------------------- | ----------------------------------------------------------------------- |
| `account.isDelegated()` | `@startale-scs/aa-sdk` | Reads the EOA's code and checks for the `0xef0100` prefix.              |
| `account.unDelegate()`  | `@startale-scs/aa-sdk` | Submits an authorization for the zero address, clearing the delegation. |

## Caveats

<Warning>
  Some external wallets restrict EIP-7702 delegation to their own implementation contracts. If your users sign through a wallet that enforces this, you cannot delegate them to the Startale implementation; use a viem `LocalAccount` or a Privy/Dynamic embedded wallet instead.
</Warning>

* The authorization is **chain-specific** unless you set `chainId = 0`. Use a fresh authorization per chain in normal flows.
* Delegating bumps the EOA's nonce, just like any other transaction.
* Reverting (`unDelegate`) also bumps the nonce.

## Next steps

<CardGroup cols={2}>
  <Card title="Smart account setup" icon="wallet" href="/aa-sdk/tutorials/smart-account-setup">
    Wire the EIP-7702 client into a React provider.
  </Card>

  <Card title="Sponsored paymaster" icon="gas-pump" href="/aa-sdk/tutorials/sponsored-tx">
    Sponsor the upgrade UserOp itself.
  </Card>

  <Card title="Smart sessions" icon="key-skeleton" href="/aa-sdk/tutorials/smart-sessions">
    Issue session keys for the upgraded EOA.
  </Card>

  <Card title="Contracts and audits" icon="folder" href="/aa-sdk/resources/contracts-and-audits">
    Look up the implementation address per network.
  </Card>
</CardGroup>
