# EIP-7702 Quickstart

EIP-7702 enables Ethereum Externally Owned Accounts (EOAs) to authorize smart contract code at their address, unlocking:

* **Gas Sponsorship**: Abstract gas fees through third-party sponsorship or ERC-20 token payments
* **Transaction Batching**: Improve UX and security by combining approvals and contract interactions atomically
* **Granular Permissions**: Grant specific, limited access to third parties for use cases like recurring payments
* **Forward Compatibility**: Maintains compatibility with ERC-4337 and future native account abstraction

Learn more in the dedicated [7702 Overview](https://docs.candide.dev/account-abstraction/7702/overview.md).

This guide demonstrates how to upgrade your EOA to a Smart Account for batching and gas sponsorship capabilities.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

* Sepolia Bundler and Paymaster endpoints from the [Dashboard](https://dashboard.candide.dev)
* Node and a package manager (yarn or npm)

Here's the [complete code](https://github.com/candidelabs/abstractionkit-examples/blob/main/eip-7702/simple-account/01-upgrade-eoa.ts) for you to reference if you prefer to run directly.

## Step 1: Get setup[​](#step-1-get-setup "Direct link to Step 1: Get setup")

1. Create a new directory for your project:

```
mkdir candide-eip7702-upgrade-eoa

cd candide-eip7702-upgrade-eoa

npx tsc --init
```

2. Install dependencies

```
npm i typescript --save-dev

npm i abstractionkit dotenv ethers
```

3. Configure Environment Variables

* Create a `.env` file and add the following environment variables with your own values

.env

```
CHAIN_ID=11155111

JSON_RPC_NODE_PROVIDER=https://ethereum-sepolia-rpc.publicnode.com

BUNDLER_URL=https://api.candide.dev/public/v3/11155111

PAYMASTER_URL=https://api.candide.dev/public/v3/11155111
```

4. Create an empty file and a function to run your script

index.ts

```
async function main(): Promise<void> {

  // Rest of the code will go here...

}



main();
```

## Step 2: Prepare Smart Account Instance[​](#step-2-prepare-smart-account-instance "Direct link to Step 2: Prepare Smart Account Instance")

Prepare the smart account instance using [Simple7702AccountV09](https://docs.candide.dev/wallet/abstractionkit/simple-7702-account-v09.md), a fully audited minimalist smart contract account safely authorized by any EOA. It provides full support for smart account features including batching and gas sponsorship.

index.ts

```
import { Simple7702AccountV09 } from "abstractionkit";

import { Wallet } from "ethers";



// For demo: generate a random EOA. In production, use user's EOA/private key

const eoaDelegator = Wallet.createRandom();



const smartAccount = new Simple7702AccountV09(eoaDelegator.address);



console.log("Smart account address (sender): " + smartAccount.accountAddress);
```

Let's run this code

Terminal

```
npx ts-node index.ts
```

If everything worked, you will see the computed smart account address in the console, which is the same as the EOA address.

Example output:

```
Account address(sender): 0x32afdcfa1e3bfe70d03ecb55b5c8045c26515c9d
```

## Step 3: Generate callData for Minting NFTs[​](#step-3-generate-calldata-for-minting-nfts "Direct link to Step 3: Generate callData for Minting NFTs")

Beyond upgrading the EOA to a smart account, this example demonstrates executing two NFT mints in a single transaction.

index.ts

```
import {

  MetaTransaction,

  getFunctionSelector,

  createCallData,

} from "abstractionkit";



// We will be minting two random NFTs in a single tx

const nftContractAddress = "0x9a7af758aE5d7B6aAE84fe4C5Ba67c041dFE5336";

const mintFunctionSignature = 'mint(address)';

const mintFunctionSelector = getFunctionSelector(mintFunctionSignature);

const mintTransactionCallData = createCallData(

    mintFunctionSelector,

    ["address"],

    [smartAccount.accountAddress]

);

const transaction1: MetaTransaction = {

    to: nftContractAddress,

    value: 0n,

    data: mintTransactionCallData,

}



const transaction2: MetaTransaction = {

    to: nftContractAddress,

    value: 0n,

    data: mintTransactionCallData,

}
```

## Step 4: Create UserOperation[​](#step-4-create-useroperation "Direct link to Step 4: Create UserOperation")

Now the fun part. Call `createUserOperation`, which will:

1. Prepare the `eip7702Auth` tuple for signature authorization. This is used during the authorization transaction of the EOA.
2. Determine the nonce and fetch the gas prices from the provided node RPC
3. Estimate gas limits from the provided bundler

This returns an unsigned user operation. Use `calculateUserOperationMaxGasCost` to calculate its cost.

index.ts

```
import {

  // ...

  calculateUserOperationMaxGasCost

} from "abstractionkit";



const bundlerUrl = process.env.BUNDLER_URL as string;

const chainId = BigInt(process.env.CHAIN_ID as string);

const eoaDelegatorPrivateKey = process.env.PRIVATE_KEY as string;

const jsonRpcNodeProvider = process.env.JSON_RPC_NODE_PROVIDER as string;



let userOperation = await smartAccount.createUserOperation(

    [transaction1, transaction2],

    jsonRpcNodeProvider,

    bundlerUrl,

    {

        eip7702Auth:{

            chainId, // chainId at which the account will be authorized

        }

    }

);



const cost = calculateUserOperationMaxGasCost(userOperation)

console.log("This useroperation may cost up to : " + cost + " wei")

console.log("Please fund the sender account : " + userOperation.sender +" with more than " + cost + " wei")
```

## Step 5: Sign the Authorization[​](#step-5-sign-the-authorization "Direct link to Step 5: Sign the Authorization")

Sign the `eip7702Auth` tuple to authorize the smart account code at your EOA address. This is only needed during the first upgrade transaction. If the EOA is already delegated, `eip7702Auth` will be `null` and signing can be skipped.

```
import { createAndSignEip7702DelegationAuthorization } from "abstractionkit"



if (userOperation.eip7702Auth) {

    userOperation.eip7702Auth = createAndSignEip7702DelegationAuthorization(

        BigInt(userOperation.eip7702Auth.chainId),

        userOperation.eip7702Auth.address,

        BigInt(userOperation.eip7702Auth.nonce),

        eoaDelegatorPrivateKey

    )

}
```

## Step 6: Get Paymaster data (Optional)[​](#step-6-get-paymaster-data-optional "Direct link to Step 6: Get Paymaster data (Optional)")

Optionally [sponsor gas](https://docs.candide.dev/wallet/guides/send-gasless-eip-7702.md) for your user transaction or offer them to pay [gas in erc-20 tokens](https://docs.candide.dev/wallet/guides/pay-gas-in-erc20-eip-7702.md).

```
import { Erc7677Paymaster } from "abstractionkit";



const paymasterUrl = process.env.PAYMASTER_URL as string;



const paymaster = new Erc7677Paymaster(paymasterUrl)



const { userOperation: paymasterUserOperation } = await paymaster.createPaymasterUserOperation(

    smartAccount,

    userOperation,

    bundlerUrl,

);



userOperation = paymasterUserOperation;
```

## Step 7: Sign and Submit[​](#step-7-sign-and-submit "Direct link to Step 7: Sign and Submit")

1. Call `signUserOperation`, which will create a signature for the private key provided of the owner of the EOA.

index.ts

```
const privateKey = process.env.PRIVATE_KEY as string;



userOperation.signature = smartAccount.signUserOperation(

    userOperation,

    privateKey,

    chainId,

);
```

2. Use the Bundler URL to send the user operation to the bundler with `sendUserOperation`, and await the return `SendUseroperationResponse` object to confirm the on-chain inclusion of the user operation.

index.ts

```
const sendUserOperationResponse = await smartAccount.sendUserOperation(userOperation, bundlerUrl)



console.log("UserOperation sent. Waiting to be included ......")
```

3. Track the userOperation and wait for its inclusion onchain

```
let userOperationReceiptResult = await sendUserOperationResponse.included()



console.log("Useroperation receipt received.")

console.log(userOperationReceiptResult)



if (userOperationReceiptResult.success) {

    console.log("EOA upgraded to a Smart Account and minted two NFTs! The transaction hash is : " + userOperationReceiptResult.receipt.transactionHash)

} else {

    console.log("Useroperation execution failed")

}
```

Now let's run this code again

Terminal

```
npx ts-node index.ts
```

You've now enabled smart account features for your EOA! If everything went well, you should see the bundler returning a user operation receipt.

Example output:

```
Useroperation sent. Waiting to be included ......

Useroperation receipt received.

{

  userOpHash: '0x89a5111d40c4ca45977a28419a08ca33e496a88e973bc995ec6a5a28da564cb5',

  entryPoint: '0x433709009B8330FDa32311DF1C2AFA402eD8D009',

  sender: '0xbdbc5fbc9ca8c3f514d073ec3de840ac84fc6d31',

  nonce: 0n,

  paymaster: '0x0000000000000000000000000000000000000000',

  actualGasCost: 243581295447n,

  actualGasUsed: 84429n,

  success: true,

  // ...

  receipt: {

    // ...

    transactionHash: '0x763dc353dee853da059b9e8c4b9997cccd4597b4cfcfc5fc3133dcffc778d93a',

    // ...

  }

}

EOA upgraded to a Smart Account and minted two NFTs! The transaction hash is : 0x763dc353dee853da059b9e8c4b9997cccd4597b4cfcfc5fc3133dcffc778d93a
```

You can look up the hash on explorers that support user operations like [Blockscout](https://www.blockscout.com/).

## Full Example[​](#full-example "Direct link to Full Example")

01-upgrade-eoa.ts

```
loading...
```

[See full example on GitHub](<https://github.com/candidelabs/abstractionkit-examples/blob/main/eip-7702/simple-account/01-upgrade-eoa.ts&#xA;>)
