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

# Account deployment

> Deploy with the first transaction and check deployment state on each chain.

A newly created smart account has a counterfactual address before it has contract code. Deployment is per chain: receiving assets at that address does not deploy it, and deployment on one chain does not deploy it everywhere.

Use the account and transaction calls from [Relay a transaction](/transactions/relaying/relay-a-transaction) for the examples below.

<Tabs>
  <Tab title="Embedded wallet">
    Embedded wallets derive and store the account address and factory data during [sign-up](/wallets/embedded-wallets/sign-up-and-sign-in). Authentication does not submit an onchain deployment transaction.

    ## Automatic deployment

    Send the first real transaction with `sendIntent()`. If the account is undeployed on the execution chain, the wallet includes its factory setup in the intent. You do not need to construct or submit a factory call yourself.

    ```ts {4,9} theme={null}
    import { baseSepolia } from "viem/chains";
    import { oneAuth } from "./oneauth";

    const result = await oneAuth.sendIntent({
      accountAddress,
      targetChain: baseSepolia.id,
      sourceChainId: baseSepolia.id,
      sourceAssets: [usdc],
      calls: [...calls],
      sponsorshipMode: "required",
      experimental_clear_signing: true,
      closeOn: "completed",
    });

    if (!result.success) {
      throw new Error(result.error?.message ?? `Intent ended as ${result.status}`);
    }
    ```

    This example uses the same-chain USDC transfer from [Relay a transaction](/transactions/relaying/relay-a-transaction), including its [clear-signing review](/wallets/embedded-wallets/clear-signing). The completed intent deploys the account on Base Sepolia if necessary, then executes the calls.

    The deployment cost is part of the route. With `sponsorshipMode: "required"`, your application must sponsor it. For a user-paid route, use `"disabled"` and fund the account with enough assets for both the calls and fees. See [Sponsor fees](/transactions/sponsorship/sponsor-fees) for setup and fallback behavior.

    ## Check deployment

    Use a public RPC client for the chain you want to check. `OneAuthClient` does not expose an `isDeployed()` method:

    ```ts theme={null}
    import { createPublicClient, http } from "viem";

    const publicClient = createPublicClient({
      chain: baseSepolia,
      transport: http(),
    });

    const code = await publicClient.getCode({ address: accountAddress });
    const deployed = code !== undefined && code !== "0x";
    ```

    Check the authenticated account's address, not an account from another application or WebAuthn mode. See [Accounts](/wallets/embedded-wallets/accounts#account-isolation) for the namespace boundaries.

    <Note>
      `@rhinestone/1auth` does not expose a standalone deployment method. Deploy
      with the first real intent; the explicit deployment examples in the Custom
      signer tab are not embedded wallet APIs.
    </Note>
  </Tab>

  <Tab title="Custom signer">
    Use `account` from the [Custom signer quickstart](/wallets/custom-signer/quickstart).

    ## Automatic deployment

    For a normal SDK intent, you do not need to call `deploy` first. When the target account is undeployed, `prepareTransaction` includes its setup operation in the quote. After you sign and submit that prepared intent, a relayer executes the setup and calls as part of the selected route.

    ```ts theme={null}
    import { baseSepolia } from "viem/chains";

    const prepared = await account.prepareTransaction({
      chain: baseSepolia,
      calls: [...calls],
    });
    const signed = await account.signTransaction(prepared);
    const submitted = await account.submitTransaction(signed);
    const result = await account.waitForExecution(submitted);
    ```

    The account is deployed only on chains where the route executes its account operations. An accepted submission is not proof of deployment; wait for completion, then call `isDeployed` when later behavior depends on the onchain code.

    <Note>
      Funding a counterfactual address is safe when you preserve its exact account
      configuration, but receiving funds alone does not execute the factory call.
    </Note>

    ### Pay deployment costs

    The deployment cost is part of the prepared route:

    * For a user-paid transaction, the route can use the user's available source assets according to the quote.
    * For a sponsored transaction, set `sponsored` while preparing the intent. Complete [Sponsorship setup](/transactions/sponsorship/set-up) first and confirm the selected quote's fee breakdown.

    A sponsorship rejection does not fall back to the user's funds at submission time. Prepare a new user-paid route and obtain a new signature if your application offers that fallback.

    ## Check deployment

    Pass the chain object, not a chain ID:

    ```ts theme={null}
    const deployed = await account.isDeployed(baseSepolia);
    ```

    For a smart account, this checks whether contract code exists at the account address on that chain. A plain EOA is already usable and reports as deployed even though there is no smart account contract.

    ## Deploy explicitly

    Call `deploy` when the account must exist before its first application transaction:

    ```ts theme={null}
    const didDeploy = await account.deploy(baseSepolia);
    ```

    The promise waits for the deployment path to complete. It returns `true` when this call performed a deployment and `false` when the account was already deployed or is a plain EOA.

    For an SDK-managed deployment through the intent path, request gas sponsorship explicitly:

    ```ts theme={null}
    const didDeploy = await account.deploy(baseSepolia, {
      sponsored: true,
    });
    ```

    Depending on the attached account data and SDK configuration, an explicit deployment can use a UserOperation instead of an intent—for example, an undeployed bring-your-own account whose Intent Executor is not installed, or an account configured with a custom bundler. In that case, configure the bundler and optional paymaster through [ERC-4337](/wallets/custom-signer/configuration/erc-4337); the relayer `sponsored` option does not configure UserOperation sponsorship.

    For EIP-7702, `deploy` creates the required initialization signature automatically. Normal `prepareTransaction` calls still require the explicit EIP-7702 flow documented in [Account types: EIP-7702](/wallets/custom-signer/configuration/account-types/eip-7702).

    ## Deploy from another account

    Use the public `deploy` action when an existing smart account should submit and pay for another account's factory call:

    ```ts {3,9} theme={null}
    import { deploy } from "@rhinestone/sdk/actions";

    const newAccount = await rhinestone.createAccount({
      owners: { type: "ecdsa", accounts: [newOwner] },
    });

    const prepared = await sponsorAccount.prepareTransaction({
      chain: baseSepolia,
      calls: [deploy(newAccount)],
    });
    const signed = await sponsorAccount.signTransaction(prepared);
    const submitted = await sponsorAccount.submitTransaction(signed);
    await sponsorAccount.waitForExecution(submitted);
    ```

    The target account derives its factory call from `newAccount` while `sponsorAccount` owns and authorizes the relay. This is separate from organization-level fee sponsorship; add `sponsored` to the prepared transaction only when your configured sponsorship should cover its fees.

    ## Supported account behavior

    | Account configuration                   | Deployment behavior                                                                                                                                                                       |
    | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Nexus, Safe, Kernel, `Startale`, or HCA | The SDK can include the provider's factory setup in an intent or deploy the account explicitly.                                                                                           |
    | EIP-7702 Nexus account                  | The SDK initializes and delegates the existing EOA address instead of creating a separate account address. Normal transaction preparation requires the EIP-7702 initialization signature. |
    | Plain EOA                               | There is no smart account to deploy. `deploy` returns `false`.                                                                                                                            |
    | Bring your own account                  | A deployed account needs no factory data. An undeployed account needs the correct address, factory, factory calldata, and Intent Executor state.                                          |

    Keep the complete account configuration unchanged across chains. Provider version, owners, salt, nonce, or factory choices can change the counterfactual address. See [Smart account providers](/wallets/custom-signer/configuration/smart-account-providers) and [Bring your own account](/wallets/custom-signer/configuration/bring-your-own-account).
  </Tab>
</Tabs>
