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

# Getting Started with EIP-7702

> Implement cross-chain contract calls using EIP-7702 delegation

This guide shows you how to implement EIP-7702 with OneBalance using a complete, runnable example. You'll build a cross-chain USDC transfer that automatically handles delegation.

<Info>
  **Working Code Examples**: Complete, production-ready EIP-7702 examples are available in our open-source repository: [OneBalance Examples - EIP-7702](https://github.com/OneBalance-io/onebalance-examples/tree/main/eip-7702). These examples include proper signature handling, multi-chain operations, and error recovery patterns.
</Info>

## Prerequisites

* OneBalance API key ([Get one here](/api-reference/authentication))
* Wallet library with `signAuthorization` support (viem)
* TypeScript/JavaScript environment

## Account Configuration

EIP-7702 accounts use your existing EOA address:

```typescript theme={null}
const account = {
  type: "kernel-v3.3-ecdsa",
  deploymentType: "EIP7702", 
  signerAddress: "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c", // Your EOA
  accountAddress: "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c"  // Same address
};
```

<Note>
  Unlike [ERC-4337 accounts](/concepts/accounts), you don't need to predict a new address. Your EOA address becomes your smart account address through delegation.
</Note>

## Step 1: Prepare Quote

Call [prepare-call-quote](/api-reference/quotes/prepare-call-quote) to analyze your requirements. If your EOA needs delegation, you'll receive delegation objects to sign:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const prepareResponse = await fetch('https://be.onebalance.io/api/quotes/prepare-call-quote', {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      account: {
        type: "kernel-v3.3-ecdsa",
        deploymentType: "EIP7702",
        signerAddress: "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c",
        accountAddress: "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c"
      },
      targetChain: "eip155:42161", // Arbitrum
      calls: [{
        to: "0xaf88d065e77c8cc2239327c5edb3a432268e5831", // USDC on Arbitrum
        data: "0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680", // transfer(address,uint256)
        value: "0x0"
      }],
      tokensRequired: [{
        assetType: "eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831",
        amount: "10000000" // 10 USDC
      }]
    })
  });

  const prepareData = await prepareResponse.json();
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://be.onebalance.io/api/quotes/prepare-call-quote' \
    -H 'x-api-key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "account": {
        "type": "kernel-v3.3-ecdsa",
        "deploymentType": "EIP7702",
        "signerAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c",
        "accountAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c"
      },
      "targetChain": "eip155:42161",
      "calls": [{
        "to": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
        "data": "0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680",
        "value": "0x0"
      }],
      "tokensRequired": [{
        "assetType": "eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831",
        "amount": "10000000"
      }]
    }'
  ```
</CodeGroup>

## Step 2: Sign Delegations

If your EOA isn't delegated yet, sign the delegation objects using viem's [`signAuthorization`](https://viem.sh/docs/eip7702/signAuthorization) method:

EIP-7702 enables EOAs to delegate execution to smart contracts. Delegation is required on **source chains** (for spending) and **destination chains** (only for contract calls).

### Delegation Signature Structure

When your EOA needs delegation, OneBalance returns a delegation object that you need to sign:

```typescript theme={null}
interface DelegationSignature {
  chainId: number;
  contractAddress: Hex; // Kernel v3.3 smart contract address
  nonce: number; // Current delegation nonce for the EOA
  r: Hex;
  s: Hex;
  v: Hex;
  yParity: number;
  type: 'Signed' | 'Unsigned';
}
```

### Signing Process

<Warning>
  **Kernel Account Signing**: EIP-7702 accounts using Kernel v3.3 require special signing patterns. Unlike role-based accounts that sign typed data, Kernel accounts sign the UserOperation hash directly.

  For complete signing documentation including error handling and troubleshooting, see the [Signing Guide](/concepts/signing).
</Warning>

```typescript theme={null}
import { privateKeyToAccount } from 'viem/accounts';
import { entryPoint07Address, getUserOperationHash } from 'viem/account-abstraction';

const signerAccount = privateKeyToAccount('0x...' as `0x${string}`);
const operation = prepareData.chainOperation;
const chainId = Number(operation.typedDataToSign.domain.chainId);

// Step 1: Sign delegation if needed
if (operation.delegation) {
  const authTuple = {
    contractAddress: operation.delegation.contractAddress,
    nonce: operation.delegation.nonce,
    chainId: chainId,
  };
  
  const signedTuple = await signerAccount.signAuthorization(authTuple);
  
  if (signedTuple.yParity == null) {
    throw new Error('Y parity is required for EIP-7702 delegation');
  }

  // Add signature to delegation object
  operation.delegation.signature = {
    chainId: chainId,
    contractAddress: signedTuple.address,
    nonce: signedTuple.nonce,
    r: signedTuple.r,
    s: signedTuple.s,
    v: `0x${Number(signedTuple.v).toString(16).padStart(2, '0')}`,
    yParity: signedTuple.yParity,
    type: 'Signed',
  };
}

// Step 2: Sign UserOperation hash (Kernel v3.3 specific)
// Deserialize UserOp with proper BigInt conversions
const deserializedUserOp = {
  sender: operation.userOp.sender,
  nonce: BigInt(operation.userOp.nonce),
  factory: operation.userOp.factory,
  factoryData: operation.userOp.factoryData,
  callData: operation.userOp.callData,
  callGasLimit: BigInt(operation.userOp.callGasLimit),
  verificationGasLimit: BigInt(operation.userOp.verificationGasLimit),
  preVerificationGas: BigInt(operation.userOp.preVerificationGas),
  maxFeePerGas: BigInt(operation.userOp.maxFeePerGas),
  maxPriorityFeePerGas: BigInt(operation.userOp.maxPriorityFeePerGas),
  paymaster: operation.userOp.paymaster,
  paymasterVerificationGasLimit: operation.userOp.paymasterVerificationGasLimit 
    ? BigInt(operation.userOp.paymasterVerificationGasLimit) : undefined,
  paymasterPostOpGasLimit: operation.userOp.paymasterPostOpGasLimit 
    ? BigInt(operation.userOp.paymasterPostOpGasLimit) : undefined,
  paymasterData: operation.userOp.paymasterData,
  signature: operation.userOp.signature,
};

// Get UserOperation hash for EntryPoint 0.7
const userOpHash = getUserOperationHash({
  userOperation: deserializedUserOp,
  entryPointAddress: entryPoint07Address,
  entryPointVersion: '0.7',
  chainId: chainId,
});

// Sign the hash directly (not typed data)
const signature = await signerAccount.signMessage({ 
  message: { raw: userOpHash } 
});

operation.userOp.signature = signature;
```

<Info>
  The [`signAuthorization`](https://viem.sh/docs/eip7702/signAuthorization) method is part of viem's EIP-7702 support. It signs an authorization that allows your EOA to delegate execution to the Kernel v3.3 smart contract. Other wallet providers like [Privy](https://docs.privy.io/wallets/using-wallets/ethereum/sign-7702-authorization) also support this method.
</Info>

<Warning>
  You must sign delegation objects for ALL chain operations returned by `prepare-call-quote` - both source and destination chains.
</Warning>

## Step 3: Get Quote

Submit the signed delegation to [call-quote](/api-reference/quotes/get-call-quote) to get the executable quote:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const quoteResponse = await fetch('https://be.onebalance.io/api/quotes/call-quote', {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      account: prepareData.account,
      chainOperation: operation, // Contains signed delegation
      tamperProofSignature: prepareData.tamperProofSignature,
      fromAggregatedAssetId: 'ob:usdc' // Specify which aggregated asset to use
    })
  });

  const quote = await quoteResponse.json();
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://be.onebalance.io/api/quotes/call-quote' \
    -H 'x-api-key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "account": {
        "type": "kernel-v3.3-ecdsa",
        "deploymentType": "EIP7702",
        "signerAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c",
        "accountAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c"
      },
      "chainOperation": {
        "delegation": {
          "contractAddress": "0xd6CEDDe84be40893d153Be9d467CD6aD37875b28",
          "nonce": 0,
          "signature": {
            "chainId": 42161,
            "contractAddress": "0xd6CEDDe84be40893d153Be9d467CD6aD37875b28",
            "nonce": 0,
            "r": "0x...",
            "s": "0x...",
            "v": "0x1c",
            "yParity": 1,
            "type": "Signed"
          }
        },
        "userOp": {
          "signature": "0x..."
        }
      },
      "tamperProofSignature": "0x...",
      "fromAggregatedAssetId": "ob:usdc"
    }'
  ```
</CodeGroup>

## Step 4: Execute

Execute the quote using [execute-quote](/api-reference/quotes/execute-quote). **Important**: You must also sign any origin chain operations:

```typescript theme={null}
// Sign origin chain operations using the same pattern as Step 2
for (let i = 0; i < quote.originChainsOperations.length; i++) {
  const originOperation = quote.originChainsOperations[i];
  // Use same signing logic as Step 2 for each origin chain operation
  // (delegation + UserOperation hash signing)
  quote.originChainsOperations[i] = await signOperation(originOperation);
}
```

<CodeGroup>
  ```typescript TypeScript theme={null}
  const executeResponse = await fetch('https://be.onebalance.io/api/quotes/execute-quote', {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(quote)
  });

  const result = await executeResponse.json();
  console.log('Transaction executed:', result);
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://be.onebalance.io/api/quotes/execute-quote' \
    -H 'x-api-key: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "quoteId": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
      "account": {
        "type": "kernel-v3.3-ecdsa",
        "deploymentType": "EIP7702",
        "signerAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c",
        "accountAddress": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c"
      },
      "chainOperations": [
        {
          "chainId": "eip155:42161",
          "userOp": {
            "sender": "0x5Cb2369421F8a00Ef556d662D6E97C1419B1d37c",
            "nonce": "0x0",
            "signature": "0x..."
          },
          "delegation": {
            "contractAddress": "0xd6CEDDe84be40893d153Be9d467CD6aD37875b28",
            "signature": {
              "chainId": 42161,
              "r": "0x...",
              "s": "0x...",
              "yParity": 1,
              "type": "Signed"
            }
          }
        }
      ]
    }'
  ```
</CodeGroup>

The operation will:

1. **Delegate** your EOA on chains that need it (automatically)
2. **Bridge** 10 USDC from source chains to the destination
3. **Execute** your contract call on the destination chain

All in a single user interaction.

## Implementation Notes

### Critical Requirements

* **Account type**: Must use `type: "kernel-v3.3-ecdsa"` and `deploymentType: "EIP7702"`
* **Address configuration**: Both `accountAddress` and `signerAddress` must be the same EOA address
* **Signing method**: Kernel accounts sign UserOperation hash (`signMessage()`) not typed data
* **Y parity validation**: Always check `signedTuple.yParity` is not null
* **Multi-chain signing**: Sign both destination operation (Step 2) and origin operations (Step 4)

### Key Differences from Role-Based Accounts

| Aspect             | Kernel v3.3 (EIP-7702)                 | Role-Based                       |
| ------------------ | -------------------------------------- | -------------------------------- |
| **Signing method** | UserOperation hash via `signMessage()` | Typed data via `signTypedData()` |
| **Address**        | Same as EOA                            | Predicted new address            |
| **EntryPoint**     | Requires 0.7                           | Not applicable                   |
| **Delegation**     | Required on spending chains            | Not applicable                   |

## Next Steps

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="wrench" href="/guides/eip-7702/troubleshooting">
    Handle common errors and multi-input scenarios
  </Card>

  <Card title="Working Examples" icon="code" href="https://github.com/OneBalance-io/onebalance-examples/tree/main/eip-7702">
    Complete production-ready code examples
  </Card>
</CardGroup>

<Check>
  Your EOA now has smart account capabilities whenever needed, without changing addresses or migrating funds.
</Check>
