This walkthrough explores two approaches to account abstraction with Para and Alchemy: EIP-7702 temporary account upgrades versus traditional smart wallet accounts. Both approaches enable gas sponsorship and advanced transaction capabilities, but work differently under the hood.

Understanding the Approaches

Traditional Smart Wallet Accounts

Traditional smart wallet accounts involve:

  1. EOA as signer/owner - Para wallet acts as the signer for a deployed smart contract
  2. Smart contract deployment - A separate smart contract wallet is deployed on-chain
  3. Smart contract receives benefits - Gas sponsorship goes to the smart contract, not the EOA
  4. Persistent deployment - The smart contract remains deployed after use

EIP-7702 Temporary Upgrades

EIP-7702 enables:

  1. EOA receives benefits directly - Para wallet itself receives gas sponsorship and smart contract capabilities
  2. No permanent deployment - Temporarily borrows bytecode from a pre-deployed smart contract
  3. EOA transformation - The EOA itself becomes a smart account temporarily
  4. Simplified architecture - No need to manage separate smart contract addresses

Key Differences

FeatureSmart Wallet AccountEIP-7702
Contract DeploymentRequired per userUses pre-deployed contract
Gas Sponsorship TargetSmart contract addressEOA address directly
Transaction ComplexityHigher (userOps)Lower (standard transactions)
Signature RecoveryExpects 27/28 v-bytesExpects 0/1 v-bytes
PersistencePermanent deploymentTemporary upgrade

Para Wallet Integration

Para wallets work as EOAs (Externally Owned Accounts) that can sign for both approaches:

  • Active user sessions - Authenticated users with live Para embedded wallets
  • Pregenerated wallets - Server-side Para instances with loaded user shares

Since Para provides raw signing capabilities, it can facilitate signatures for both smart wallet accounts and EIP-7702 operations.

Implementation: Smart Wallet Accounts

Setup Para Client

import { Para, Environment } from "@getpara/server-sdk";
import { createParaAccount, createParaViemClient } from "@getpara/viem";

// Initialize Para with pregenerated wallet
const para = new Para(Environment.BETA, process.env.PARA_API_KEY!);

// Load user share for pregenerated wallet
const userShare = await getUserShareFromDatabase(email);
await para.setUserShare(userShare);

// Create Para account with custom signing
const viemParaAccount = createParaAccount(para);
viemParaAccount.signMessage = async ({ message }) => 
  customSignMessage(para, message);

Create Alchemy Modular Account Client

import { customSignMessage } from "./signature-utils";

// Create Viem client with Para integration
const viemClient = createParaViemClient(para, {
  account: viemParaAccount,
  chain: arbitrumSepolia,
  transport: http(rpcUrl)
});

// Create wallet client signer
const walletClientSigner = new WalletClientSigner(viemClient, "para");

// Create Alchemy modular account client
const alchemyClient = await createModularAccountAlchemyClient({
  transport: alchemy({ rpcUrl: rpcUrl }),
  chain: arbitrumSepolia,
  signer: walletClientSigner,
  policyId: alchemyGasPolicyId // For gas sponsorship
});

Execute Smart Wallet Transactions

// Prepare batch user operations
const uoCallData = await alchemyClient.buildUserOperation({
  calls: [
    {
      target: "0x1234567890123456789012345678901234567890",
      data: "0x",
      value: parseEther("0.001")
    }
  ]
});

// Send user operation
const { hash: uoHash } = await alchemyClient.sendUserOperation(uoCallData);

// Wait for confirmation
const txHash = await alchemyClient.waitForUserOperationTransaction({
  hash: uoHash
});

console.log(`Smart wallet transaction: ${txHash}`);

Implementation: EIP-7702

Setup Para Client

import { Para, Environment } from "@getpara/server-sdk";
import { createParaAccount, createParaViemClient } from "@getpara/viem";

// Initialize Para with pregenerated wallet
const para = new Para(Environment.BETA, process.env.PARA_API_KEY!);

// Load user share for pregenerated wallet
const userShare = await getUserShareFromDatabase(email);
await para.setUserShare(userShare);

// Create Para account with custom signing
const viemParaAccount = createParaAccount(para);
viemParaAccount.signMessage = async ({ message }) => 
  customSignMessage(para, message);

Create EIP-7702 Client

// Create Viem client
const viemClient = createParaViemClient(para, {
  account: viemParaAccount,
  chain: arbitrumSepolia,
  transport: http(rpcUrl)
});

const walletClientSigner = new WalletClientSigner(viemClient, "para");

// Create EIP-7702 client - note the "mode" parameter
const alchemyClient = await createModularAccountV2Client({
  mode: "7702", // This is the key difference
  transport: alchemy({ rpcUrl: rpcUrl }),
  chain: arbitrumSepolia,
  signer: walletClientSigner,
  policyId: alchemyGasPolicyId
});

Execute EIP-7702 Transactions

// EIP-7702 transactions are simpler
const txHash = await alchemyClient.sendTransaction({
  calls: [
    {
      target: "0x1234567890123456789012345678901234567890",
      data: "0x",
      value: parseEther("0.001")
    }
  ]
});

console.log(`EIP-7702 transaction: ${txHash}`);

Signature Compatibility

Para’s MPC signatures use 0/1 v-byte recovery, but smart wallet accounts expect 27/28. You need custom signing utilities:

Custom Signature Utils

// signature-utils.ts
const V_OFFSET_FOR_ETHEREUM = 27;

export async function customSignMessage(para: Para, message: string | Uint8Array) {
  const messageToSign = typeof message === "string" ? message : toHex(message);
  const signature = await para.signMessage(messageToSign);
  
  // Parse signature components
  const r = signature.slice(0, 64);
  const s = signature.slice(64, 128);
  let v = parseInt(signature.slice(128, 130), 16);
  
  // Adjust v-byte for smart wallet compatibility
  if (v < 27) {
    v += V_OFFSET_FOR_ETHEREUM;
  }
  
  return `0x${r}${s}${v.toString(16).padStart(2, "0")}`;
}

export async function customSignAuthorization(para: Para, authorization: any) {
  const signature = await para.signMessage(serializeAuthorization(authorization));
  
  // Parse v-byte
  const v = parseInt(signature.slice(128, 130), 16);
  
  // EIP-7702 requires v-byte of 0 or 1
  if (v !== 0 && v !== 1) {
    throw new Error(`Invalid v value for EIP-7702: ${v}. Expected 0 or 1`);
  }
  
  return `0x${signature}`;
}

Apply Custom Signing

// Override Para account signing methods
viemParaAccount.signMessage = async ({ message }) => 
  customSignMessage(para, message);

viemParaAccount.signTransaction = async (transaction) => 
  customSignTransaction(para, transaction);

Transaction Construction Best Practices

Para signs raw bytes without transaction validation. Ensure proper transaction construction:

Type Safety

// Ensure proper types before signing
const calls = [
  {
    target: getAddress("0x1234567890123456789012345678901234567890"), // Proper address format
    data: "0x" as Hex, // Proper hex format
    value: parseEther("0.001") // Proper bigint value
  }
];

Error Handling

try {
  const txHash = await alchemyClient.sendTransaction({ calls });
  console.log(`Transaction successful: ${txHash}`);
} catch (error) {
  if (error.message.includes("signature verification failed")) {
    console.error("Signature issue - check v-byte adjustment");
  } else if (error.message.includes("invalid transaction")) {
    console.error("Transaction construction issue - check types and values");
  }
  throw error;
}

Choosing the Right Approach

Use Smart Wallet Accounts When:

  • You need persistent smart contract functionality
  • Your application requires complex access control
  • You want to leverage established userOp infrastructure
  • Gas sponsorship policies are account-specific

Use EIP-7702 When:

  • You want simpler transaction flows
  • Gas sponsorship should go directly to EOAs
  • You prefer avoiding permanent contract deployments
  • Your use case fits temporary smart account capabilities

Important Considerations

Signature Recovery

  • Smart Wallet Accounts: Expect 27/28 v-byte recovery (legacy Ethereum format)
  • EIP-7702: Expects 0/1 v-byte recovery (modern format)
  • Para Default: Produces 0/1 v-byte signatures (requires adjustment for smart wallets)

Network Support

  • EIP-7702 requires network support for the new transaction type
  • Smart wallet accounts work on any EVM-compatible network
  • Check Alchemy’s documentation for current EIP-7702 network availability

Gas Sponsorship

  • Both approaches support Alchemy’s gas sponsorship policies
  • EIP-7702 sponsors the EOA directly
  • Smart wallet accounts sponsor the smart contract address

Additional Resources

For more detailed information about EIP-7702 implementation with Alchemy, see the Alchemy Modular Account v2 EIP-7702 documentation.

Next Steps