Skip to content
Alchemy Logo

Managing ownership on Modular Account V2

You can add an owner to your account, or transfer ownership of your account with Modular Account V2.

To transfer ownership, call the updateFallbackSignerData function. Modular Account V2s achieve huge savings on creation because the owner address is cached in immutable bytecode on account creation. When transferring ownership, the fallback is set to the new owner address and this will be used during validation. The boolean is set to false for the account to check this value in storage instead of the immutable cached owner address.

Note that updateFallbackSignerData is an ownership transfer operation, and the previous owner would lose access to the account. To add an owner, you should add a session key with root permissions instead.

import { createBundlerClient } from "viem/account-abstraction";
import { createClient, encodeFunctionData, type Address } from "viem";
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
import { sepolia } from "viem/chains";
import { alchemyTransport } from "@alchemy/common";
import {
  toModularAccountV2,
  semiModularAccountV2StaticImpl,
} from "@alchemy/smart-accounts";
import { estimateFeesPerGas } from "@alchemy/aa-infra";
 
const ALCHEMY_API_KEY = "your-api-key";
const transport = alchemyTransport({ apiKey: ALCHEMY_API_KEY });
const rpcClient = createClient({ chain: sepolia, transport });
 
const account = await toModularAccountV2({
  client: rpcClient,
  owner: privateKeyToAccount(generatePrivateKey()),
});
 
const bundlerClient = createBundlerClient({
  account,
  client: rpcClient,
  chain: sepolia,
  transport,
  userOperation: { estimateFeesPerGas },
});
 
const newOwner: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";
 
// `isFallbackSignerDisabled = false` keeps the fallback storage slot active for validation.
const data = encodeFunctionData({
  abi: semiModularAccountV2StaticImpl.accountAbi,
  functionName: "updateFallbackSignerData",
  args: [newOwner, false],
});
 
const hash = await bundlerClient.sendUserOperation({
  calls: [{ to: account.address, data }],
});
await bundlerClient.waitForUserOperationReceipt({ hash });
Was this page helpful?