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

# Smart Accounts

> ERC-4337 session keys for delegated agent execution

Smart accounts let the AI agent trade on your behalf without requiring a signature popup for every transaction. Using ZeroDev Kernel and ERC-4337, you create **session keys** with granular permissions -- spending limits, allowed contracts, and expiration times -- so the agent operates autonomously within your defined boundaries.

## Why Smart Accounts?

Traditional EOA wallets require the user to approve every transaction. This breaks the agent experience -- you cannot ask the agent to execute a multi-step DeFi strategy if each step requires manual wallet confirmation.

Smart accounts solve this with **delegated execution**:

<CardGroup cols={3}>
  <Card title="No Signing Popups" icon="signature">
    The agent uses a session key to sign transactions without prompting you for each one.
  </Card>

  <Card title="Granular Permissions" icon="shield-check">
    Session keys are scoped to specific contracts, function selectors, and spending limits.
  </Card>

  <Card title="Batched Transactions" icon="layer-group">
    Multiple DeFi operations (swap + stake + LP) execute atomically in a single UserOperation.
  </Card>
</CardGroup>

## Architecture

The smart account system uses three layers:

```
Your Wallet (EOA owner)
  |
  v
ZeroDev Kernel (ERC-4337 smart account)
  |
  v
Session Key (scoped permissions via CallPolicy)
  |
  v
Agent executes trades using the session key
```

### ZeroDev Kernel

The `AgentSmartAccount` class wraps [ZeroDev Kernel](https://zerodev.app/), an ERC-4337 smart account implementation. Kernel provides:

* **ECDSA validator**: your EOA is the sudo owner
* **Permission plugins**: session keys are installed as regular (non-sudo) validators
* **Batched execution**: `executeBatch()` combines multiple calls into one UserOperation
* **Gas sponsorship**: transactions can be sponsored via the Pimlico paymaster

### EntryPoint

All UserOperations are submitted to the ERC-4337 EntryPoint contract:

| Contract        | Address                                      |
| --------------- | -------------------------------------------- |
| EntryPoint v0.7 | `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` |
| Pimlico Bundler | `0x4337001fff419768e088ce247456c1b892888084` |

<Info>
  The Pimlico bundler processes UserOperations and submits them to the EntryPoint. It also provides paymaster functionality for gas sponsorship -- users do not need ETH for gas if sponsorship is enabled.
</Info>

## Session Keys

Session keys are the core mechanism for safe agent delegation. Each session key is an ephemeral private key with constrained permissions enforced on-chain by the Kernel permission plugin.

### Creating a Session Key

```typescript theme={"theme":{"light":"dracula","dark":"dracula"}}
const sessionKey = await smartAccount.createSessionKey({
  validUntil: Math.floor(Date.now() / 1000) + 86400, // 24 hours
  spendingLimitUsdc: 1000_000000n, // 1,000 USDC (6 decimals)
  allowedTargets: [
    "0x4c60051384bd2d3c01bfc845cf5f4b44bcbe9de5", // Uniswap UniversalRouter
    "0x794a61358D6845594F94dc1DB02A252b5b4814aD", // Aave V3 Pool
  ],
  allowedSelectors: [
    "0x3593564c", // execute (UniversalRouter)
    "0x617ba037", // supply (Aave)
  ],
});
```

### Session Key Parameters

| Parameter           | Type        | Description                                         |
| ------------------- | ----------- | --------------------------------------------------- |
| `validUntil`        | `number`    | Unix timestamp when the session key expires         |
| `spendingLimitUsdc` | `bigint`    | Maximum USDC the session key can spend (6 decimals) |
| `allowedTargets`    | `Address[]` | Contract addresses the key may call                 |
| `allowedSelectors`  | `Hex[]`     | Optional: restrict to specific function selectors   |

### On-Chain Enforcement

When `@zerodev/sdk` is installed, session keys are enforced on-chain through Kernel's permission plugin:

1. The agent creates an ECDSA signer from the session private key
2. A **CallPolicy** is constructed with the allowed targets and selectors
3. A **PermissionValidator** is registered that wraps the signer and policies
4. A session-scoped Kernel account is created with the permission validator as the regular validator
5. UserOperations signed by the session key are validated on-chain against the policy

<Warning>
  If `@zerodev/sdk` is not installed, session keys are generated locally but permissions are NOT enforced on-chain. The agent still respects the limits in software, but there is no smart contract guarantee. Install the full SDK for production use.
</Warning>

### CallPolicy

The `CallPolicy` is the heart of session key security. It defines exactly what the session key can do:

| Constraint   | Description                                       |
| ------------ | ------------------------------------------------- |
| `target`     | The contract address the key may call             |
| `valueLimit` | Maximum ETH value per call (0 = no ETH transfers) |
| `sig`        | Function selector restriction (optional)          |

Multiple permissions can be combined in a single CallPolicy, allowing the session key to interact with several contracts while still being tightly scoped.

## Batched Execution

One of the most powerful features of smart accounts is atomic batched execution. Instead of sending 3 separate transactions (approve + swap + supply), the agent can bundle them into a single UserOperation:

```typescript theme={"theme":{"light":"dracula","dark":"dracula"}}
const hash = await smartAccount.batchExecute([
  { target: usdcAddress, data: approveCalldata, value: 0n },
  { target: routerAddress, data: swapCalldata, value: 0n },
  { target: aavePoolAddress, data: supplyCalldata, value: 0n },
]);
```

All three calls succeed or fail together. This eliminates the risk of partial execution where a swap succeeds but the subsequent supply fails.

<Tip>
  Batched execution also saves gas. A single UserOperation with 3 internal calls costs less than 3 separate transactions because it avoids repeated base transaction overhead.
</Tip>

### Fallback Behavior

The `batchExecute` method has a graceful degradation chain:

1. **Session key client** -- if a session key is provided and a session-scoped Kernel client exists, uses it
2. **Owner Kernel client** -- if ZeroDev SDK and Pimlico are configured, submits as a batched UserOperation
3. **Deployed smart account** -- if the Kernel account is deployed on-chain, sends batch calldata directly
4. **EOA sequential** -- if no smart account exists, executes calls one at a time from the owner EOA

## Gas Sponsorship

With a Pimlico API key configured, the smart account can sponsor gas for users. The Pimlico paymaster covers the gas cost of UserOperations, so users do not need ETH in their wallet to interact with DeFi protocols.

```typescript theme={"theme":{"light":"dracula","dark":"dracula"}}
const hash = await smartAccount.sponsoredExecute({
  target: poolAddress,
  data: supplyCalldata,
  value: 0n,
});
// User pays nothing for gas -- Pimlico covers it
```

<Note>
  Gas sponsorship requires a Pimlico API key. The paymaster is configured during `AgentSmartAccount.init()` if the key is provided.
</Note>

## Web Frontend Integration

The web UI integrates smart accounts with the **Dynamic Labs** wallet SDK:

1. User connects their wallet via Dynamic Labs (supports MetaMask, WalletConnect, Coinbase Wallet, etc.)
2. The frontend derives a ZeroDev Kernel address from the connected wallet
3. User approves a session key with their desired permissions
4. The session key is stored in `sessionStorage` for the browser session
5. All subsequent agent actions use the session key -- no more wallet popups

### Session Recovery

If the browser tab is refreshed, the `useChat` hook recovers the active session from `sessionStorage` and reconnects to the agent thread. The session key remains valid until its `validUntil` timestamp expires.

## Revoking Session Keys

Session keys can be revoked immediately:

```typescript theme={"theme":{"light":"dracula","dark":"dracula"}}
const revoked = smartAccount.revokeSessionKey(sessionKeyAddress);
// Returns true if the key was found and removed
```

This removes the session-scoped Kernel client from memory. The on-chain validator remains installed but the agent can no longer use it to sign UserOperations.

<Warning>
  Revoking a session key in the `AgentSmartAccount` class only removes the local client. For full on-chain revocation, the Kernel permission validator must be uninstalled via a sudo UserOperation. This is not yet automated.
</Warning>

## SDK Reference

The smart account is in the `@arb-agent/smart-account` package as `AgentSmartAccount`.

### Constructor

```typescript theme={"theme":{"light":"dracula","dark":"dracula"}}
const account = new AgentSmartAccount({
  ownerPrivateKey: "0x...",
  rpcUrl: "https://arb1.arbitrum.io/rpc",       // optional
  pimlicoApiKey: "pk_...",                       // optional, enables UserOps
});
```

### Methods

| Method                             | Description                                               |
| ---------------------------------- | --------------------------------------------------------- |
| `init()`                           | Initialize the Kernel account and optional Pimlico client |
| `createSessionKey(params)`         | Create a scoped session key with on-chain permissions     |
| `batchExecute(calls, sessionKey?)` | Execute multiple calls atomically                         |
| `sponsoredExecute(call)`           | Execute a single call with gas sponsorship                |
| `revokeSessionKey(address)`        | Revoke a session key locally                              |

### Properties

| Property  | Type      | Description                                     |
| --------- | --------- | ----------------------------------------------- |
| `address` | `Address` | The smart account address (call `init()` first) |

## Example Prompts

```
Create a session key that can trade on Uniswap for 24 hours with a 500 USDC limit
```

```
Execute a swap and supply in one transaction
```

```
What's my smart account address?
```

```
Revoke my current session key
```
