# Frequently asked questions

> Learn how to get started with Wallet APIs, a vertically

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

<Warning>
  Check out [GitHub
  discussions](https://github.com/alchemyplatform/aa-sdk/discussions) for more
  commonly asked questions and support.
</Warning>

## Smart wallets - Light Account

### Do accounts have the same address across all chains?

<Accordion title="Answer">
  In almost all cases, yes, you get the same address on all chains as long as the connecting owner address is the same. The deployment address is a function of the owner address, the account implementation (e.g. latest version of Light Account), and the salt (you can optionally specify this). If all three remain the same, the smart wallet deploys at the same contract address.

  There are two scenarios where you would get a different contract address:

  1. If you deploy one smart wallet, then change the owner, then deploy the second account.
  2. If you upgrade the smart wallet (e.g. to a new version of Light Account). Updates to this contract are infrequent, so the address will not change often.
</Accordion>

### How does a smart wallet get deployed?

<Accordion title="Answer">
  Your smart wallet deploys when the first `UserOperation` (UO) is
  sent from the account. The first UO must be sent with a non-zero `initCode`.
  aa-sdk handles generation of this `initCode` for you using
  [`getAccountInitCode`](/docs/wallets/reference/aa-sdk/core/functions/toSmartContractAccount).
</Accordion>

### How do I upgrade a Light Account?

<Accordion title="Answer">
  You are unlikely to need to frequently update the Light Account contract
  itself, however it is possible if needed. Light Account has
  [`UUPSUpgradeable`](https://github.com/alchemyplatform/light-account/blob/main/src/LightAccount.sol#L50)
  which adds upgrade methods on the account itself. To upgrade an account,
  send a `UserOperation` using the method `upgradeTo` or
  `upgradeToAndCall`, depending on whether or not you need to initialize the new
  implementation.
</Accordion>

### Multiple accounts per owner and salt values

<Accordion title="Answer">
  Yes! The optional salt value on Light Account enables the ability to have
  multiple accounts under a single owner. This value defaults to 0. You can set
  it when you create a Light Account.
</Accordion>

### How do I upgrade from Simple Account to Light Account?

<Accordion title="Answer">
  [Simple Account's](https://github.com/eth-infinitism/account-abstraction/blob/cc3893bcaf2272c163ce89d5eb9eadb8e6b52db7/contracts/accounts/SimpleAccount.sol#L22) support [`upgradeToAndCall`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4e7e6e54daedf091d91f2f2df024cbb8f253e2ef/contracts/proxy/utils/UUPSUpgradeable.sol#L86) implemented by OpenZeppelin [UUPSUpgradeable](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable) contract. This allows you to upgrade from Simple Account to Light Account without changing the wallet address. Using `upgradeToAndCall` updates the underlying implementation contract on the account while the account address and assets stay the same.

  You can call `upgradeToAndCall` on the Simple Account with these params:

  * `newImplementation`: Latest LightAccount implementation address (found [here](https://github.com/alchemyplatform/light-account/tree/develop/deployments) - make sure to use the implementation address, not the factory address)
    * For example LightAccount v1.1.0 - 0xae8c656ad28F2B59a196AB61815C16A0AE1c3cba
  * `data`: encoded version of the `initialize` function with `anOwner` parameter set to the owner on the account, usually the same owner as what the account used as Simple Account.
    * In solidity (foundry) you can use abi.encodeCall and in viem you can use [encodeFunctionData](https://github.com/alchemyplatform/light-account/tree/develop/deployments)

  Encode the `initialize` step correctly to ensure the account does not get into a risky state where someone else could call initialize on it with their own key and take control of your account. Call `owner()` on the account after the upgrade to verify it is assigned correctly.

  This can be called on the existing smart wallet by sending a user operation that calls `execute` (or `executeBatch`) and has that call `upgradeToAndCall` (the same way you would make the account send calls to other addresses).
</Accordion>

## Submitting transactions

### `UserOperation` speed vs normal transactions

<Accordion title="Answer">
  If the `UserOperation` (meta-transaction for 4337 accounts) is correctly
  priced and submitted a few hundred milliseconds before a new block gets
  created, it will typically land in the next block. The transaction sender
  needs time to create/propagate its transaction. You can think of it as
  1 extra block time worth of latency.
</Accordion>

### Delayed `UserOperation` landing

<Accordion title="Answer">
  This can happen when `UserOperation`s (UOs) become underpriced, frequently due to fee market movement between when gas and fees are estimations and when the UO is actually submitted.

  You may experience this when calling the [`waitForUserOperationTransaction`](/docs/wallets/reference/aa-sdk/core/variables/waitForUserOperationTransaction) method. It may throw an error if it does not find the UO in a mined Transaction within its retry limits.

  You can mitigate this by defining a more flexible retry period when constructing a [`Client`](/docs/wallets/reference/aa-sdk/core/functions/createSmartAccountClient) (i.e. `txMaxRetries`, `txRetryIntervalMs`, `txRetryMultiplier` in `opts`). If your UO continues to be delayed beyond a limit you are willing to wait, you can resubmit it using [`dropAndReplaceUserOperation`](/docs/wallets/reference/aa-sdk/core/functions/dropAndReplaceUserOperation).
</Accordion>

### Are `UserOperation`s protected from MEV bots?

<Accordion title="Answer">
  Right now, `UserOperation`s are sent to a private mempool for all networks
  other than Polygon, where there is no way to do this.
</Accordion>

## Gas estimation

### How does gas estimation for 4337 smart wallets work?

<Accordion title="Answer">
  The transaction sender estimates gas and submits `UserOperation`s (UOs) under the hood of the aa-sdk. Gas estimations optimize for UOs landing onchain, and you may need to adjust gas limits based on your needs using [overrides](https://github.com/alchemyplatform/aa-sdk/blob/v4.x.x/aa-sdk/core/src/types.ts#L97).

  Learn more about gas estimation and how it is implemented in the [transaction sender blog post](https://www.alchemy.com/blog/erc-4337-gas-estimation).

  There are many nuances and edge cases that the transaction sender considers especially for L2s. Learn more in the [L2 gas and signature aggregators blog post](https://www.alchemy.com/blog/l2-gas-and-signature-aggregators).

  Add error handling when sending a UO to handle potential gas and fee changes due to market movement. Learn more about [frequent errors](#common-errors).
</Accordion>

## Gas sponsorship

### What tiers support gas sponsorship?

<Accordion title="Answer">
  Gas sponsorship is available on testnet for all tiers. For support on mainnet,
  you must be on a paying tier (i.e. Growth tier and above). Learn more about
  the different pricing tiers
  [here](https://alchemy.com/docs/reference/gas-manager-coverage-api-pricing#fee-logic).
</Accordion>

### How is gas sponsored? Do I need to fund the Gas Manager?

<Accordion title="Answer">
  Gas is fronted for your application and the USD equivalent appears on your bill
  at the end of the month. No need to worry about pre-funding the Gas Manager or
  conversions. Follow [the gas sponsorship guide](/docs/wallets/transactions/sponsor-gas) for
  more details on how to sponsor `UserOperation`s.
</Accordion>

### What are my gas sponsorship limits?

<Accordion title="Answer">
  You can find details of Gas Manager limits depending on your tier
  [here](https://alchemy.com/docs/reference/gas-manager-coverage-api-pricing#fee-logic).
</Accordion>

### Is paying gas with ERC-20 tokens or stablecoins supported?

<Accordion title="Answer">
  Yes. Gas Manager includes an ERC-20 paymaster contract so your users can pay fees with
  tokens like USDC. See [How to pay gas with any
  token](/docs/reference/how-to-pay-gas-with-any-token) for details.
</Accordion>

### How is the Gas Manager protected from DDoS attacks?

<Accordion title="Answer">
  In your Gas Manager policy, you can configure spending rules per address, per
  app, and/or policy wide limits. See how to set up these policies
  [here](/docs/wallets/transactions/sponsor-gas/conditional-sponsorship-rules).
</Accordion>

### Backend user authentication and sessions

<Accordion title="Answer">
  After a user logs in with Wallet APIs on the frontend, you might want to verify their identity on your backend to authorize actions or access.

  You can do this using one of two approaches:

  ***

  ### Option 1: SIWE [Sign-In With Ethereum](https://eips.ethereum.org/EIPS/eip-4361)

  Use this flow to verify user sessions created by EOAs and smart wallets via Wallet APIs.

  For EOAs, Wallet APIs doesn’t create a session on the client side and `stampWhoAmI` isn’t available, so use SIWE instead. This works for verifying both EOA and SCA flows.
  Create a [SIWE message](https://docs.login.xyz/sign-in-with-ethereum/quickstart-guide/creating-siwe-messages) with all the necessary info to get server side (address, chainId, etc).

  1. The backend provides a nonce to the frontend.
  2. The user signs a SIWE message with their wallet (EOA or SCA).
  3. The frontend sends the signed message back to the backend.
  4. The backend verifies the signature:

  * EOAs: Standard signature recovery
  * SCAs: Use EIP-1271 or EIP-6492 to verify the contract signature

  5. The backend issues a session token.

  **Note:**

  * SIWE requires an explicit signature from the user, which [costs](https://www.alchemy.com/docs/reference/compute-unit-costs) more than calling `whoami`
  * For verifying both EOA and SCA user sessions

  ***

  ### Option 2: `stampWhoAmI` + `whoami` (only when using the authentication service)

  Use this flow when you need to verify user sessions created by SCAs via Wallet APIs.

  1. The frontend generates a stamped request using [signer.inner.stampWhoAmI](https://www.alchemy.com/docs/wallets/reference/account-kit/signer/classes/BaseSignerClient#stampwhoami).
  2. It sends the stamp to your backend.
  3. The backend calls the [/signer/v1/whoami](https://www.alchemy.com/docs/node/smart-wallets/signer-api-endpoints/signer-api-endpoints/auth-user) endpoint to verify the identity.
  4. If you need to make subsequent requests, you can avoid calling the whoami endpoint on every request. After verifying the `whoami`, the backend can issue its own session token (e.g. an HTTP-only cookie or access token). If the token is present, you can safely skip the `whoami` check.

  **Why this approach?**

  * No user signature required
  * **Cheaper** than flows requiring a signed message
  * Retrieve user's login info, such as email and address if available
</Accordion>

## Common errors

### Replacement underpriced: `"code":-32602,"message":"replacement underpriced","data"...`

<Accordion title="Answer">
  Replacement underpriced errors occur when you attempt to send another user
  operation (UO) from the same sender before the pending user operation has been
  confirmed onchain. Please follow recommendations
  [here](https://www.alchemy.com/support/how-to-fix-replacement-underpriced-errors).
</Accordion>

### `FailedToFindTransactionError: Failed to find transaction for user operation...`

<Accordion title="Answer">
  Please follow [this](https://www.alchemy.com/support/best-practice-guide-on-how-to-implement-user-operation-retries) guide for best practices on implementing waiting and retries.

  This error indicates that your User Operation has not yet landed onchain (assuming it was accepted by the transaction sender). 1) Continue waiting or 2) drop and replace and 3) add a multiplier to gas estimates to increase the priority of your transaction.
</Accordion>

### Invalid policy ID: `{ code: -32602, message: 'Invalid Policy ID' }`

<Accordion title="Answer">
  Gas Manager policies can only be tied to one app. Make sure you are using the
  API key that is associated with the app the Gas Manager policy is configured
  for, or create a new policy for the app you are using.
</Accordion>

### Precheck failed: `{ code: -3200, message: 'precheck failed: ...' }`

<Accordion title="Answer">
  Precheck failed errors are often related to gas and/or fees. The transaction sender follows the standard [ERC-4337](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4337.md#client-behavior-upon-receiving-a-useroperation) implementation for gas and fee checks to 1) ensure your `UserOperation`s (UOs) land onchain and 2) protect the transaction sender from potential attacks to support scalability.

  These errors are often related to market movement between the time when gas and fees are estimated and the time when UOs are submitted to the transaction sender. This fluctuation in the market is especially variant on testnet. To ensure your UO is included in a block, any UOs that are underpriced compared to the network rate are rejected.

  To handle these errors, use the [override fields](https://github.com/alchemyplatform/aa-sdk/blob/v4.x.x/aa-sdk/core/src/types.ts#L97) to increase buffers on top of the estimates and implement retry mechanisms as needed.
</Accordion>

### Total execution gas limit exceeded: `{ code: -3202, message: 'precheck failed: total execution gas is X but must be at most 10000000}`

<Accordion title="Answer">
  Currently the transaction sender allows max 10M gas in aggregate between
  `preVerificationGas`, `verificationGasLimit`, and `callGasLimit`. To reduce
  the gas needed, try reducing the size of your call data and/or sending your
  call data in multiple `UserOperation`s rather than one.
</Accordion>

### `waitForUserOperationTransaction` timeout

<Accordion title="Answer">
  [`waitForUserOperationTransaction`](/docs/wallets/reference/aa-sdk/core/variables/waitForUserOperationTransaction) may throw this error if it does not find the mined User Operation within its retry limits.

  You can mitigate this by defining a more flexible retry period when constructing a [`Client`](/docs/wallets/reference/aa-sdk/core/functions/createSmartAccountClient) (i.e. `txMaxRetries`, `txRetryIntervalMs`, `txRetryMultiplier` in `opts`).

  If your `UserOperation` continues to be delayed beyond a limit you are willing to wait, you can resubmit the user operation using [`dropAndReplaceUserOperation`](/docs/wallets/reference/aa-sdk/core/functions/dropAndReplaceUserOperation#usage).
</Accordion>

### `Although one or more Error Occurred [execution reverted] Contract Execution Completed` on etherscan

<Accordion title="Answer">
  This revert warning message is expected when using Modular Account v1. In
  MAv1, a checker enforces that calls made using the account (from
  `execute` or `executeBatch`) don't target plugin contracts. When the contract
  being called to isn't a plugin (which is usually the case), the checker
  reverts, and it shows this message in explorers.
</Accordion>

### `ERR_BLOCKED_BY_CLIENT` when loading the page

<Accordion title="Answer">
  This message is usually triggered by browser ad-blocking tools that stop
  analytics scripts from running. Analytics collection will be blocked, but the
  Smart Wallet functionality continues to work normally.
</Accordion>

### `User operation must include a paymaster for sponsorship` / `This network requires sponsored operations`

<Accordion title="Answer">
  These errors show up when you submit `UserOperation`s on Polygon PoS using the
  transaction sender without a paymaster contract, or with a non-compatible paymaster contract address. Polygon
  PoS now requires sponsored operations through a compatible paymaster contract. Double-check that your request includes the correct
  paymaster contract address and that your config points to the right
  paymaster contract.

  You can confirm the requirement and see the latest details in the Polygon PoS
  chain reference:
  [https://www.alchemy.com/docs/wallets/resources/chain-reference/polygon-pos#transactions](https://www.alchemy.com/docs/wallets/resources/chain-reference/polygon-pos#transactions).

  If you need help getting set up, contact
  [support@alchemy.com](mailto:support@alchemy.com).
</Accordion>

## Other support

### Does the aa-sdk repo support React Native?

No, the `aa-sdk` repo does not officially support React Native.

Currently there is a strong dependency on Viem, which requires several global features, such as `TextEncoder` and `crypto`, that are absent in React Native’s environment. See more about [Viem’s capability](https://viem.sh/docs/compatibility).

However, a small PoC using Expo is available [here](https://github.com/alchemyplatform/aa-sdk-rn-expo/tree/main). For more information on how to use Wallet APIs within a React Native application see [the guide](/docs/wallets/react-native/overview).

### How do I protect my API key and policy id in the frontend?

**Why is it important to protect your API key and Policy ID?**

To prevent unauthorized use or abuse of your API key and Policy ID, avoid exposing them on the frontend. If these credentials are exposed, they could be misused, leading to unintended usage or sponsorship.

Gas sponsorship requests only succeed if both the Policy ID and the corresponding API key are used together. While protecting your API key alone renders the Policy ID useless to malicious actors, the best security practice is to protect both.

**How to protect your API key**

Move your API key to the backend by routing to a proxy. See an [example](https://github.com/alchemyplatform/aa-sdk/blob/ef7303333830df53a9106ba37ce015675a276cd9/examples/ui-demo/src/app/config.tsx#L74) of setting up a transport to a backend rpcUrl in the demo app.

For more information on how to secure your API key, refer to the [key security and management guide](https://alchemy.com/docs/best-practices-for-key-security-and-management).

<Warning>
  If you have logic in your proxy that restricts certain paths, ensure that the
  relative paths for network-agnostic RPC requests and signer API requests ([see
  example
  here](https://github.com/alchemyplatform/aa-sdk/blob/14187f8b87224d8730da2919575ac753626461eb/examples/ui-demo/src/app/api/rpc/%5B...routes%5D/route.ts#L21)),
  and network-specific RPC requests ([see example
  here](https://github.com/alchemyplatform/aa-sdk/blob/14187f8b87224d8730da2919575ac753626461eb/examples/ui-demo/src/app/api/rpc/route.ts))
  are preserved when forwarding.
</Warning>

**How to protect your Policy ID**

Protecting your Policy ID requires some custom work, but it’s similar to safeguarding any key on the backend. One solution is to use a proxy server that holds both the API key and Policy ID. In the frontend, when creating a client, pass the proxy server URL as the RPC URL instead of a public URL.

Additionally, implement custom code on your proxy server to limit gas sponsorship requests. This could include rules that make sense for your app, such as limiting gas fees, restricting certain contract or method calls, or implementing limits based on IP addresses or CAPTCHA verification.

### Why are my users getting logged out unexpectedly?

**Issue:**\
You or your users might notice that the session ends sooner than expected, requiring re-authentication.

**Default behavior:**\
By default, authenticated sessions using `AlchemyWebSigner` are stored in `localStorage` and expire after **15 minutes** of inactivity.

***

#### Solution: extend or configure session duration

You can customize the session timeout by passing a `sessionConfig` object to the `createConfig` method:

```ts
createConfig({
  ...,
  sessionConfig: {
    expirationTimeMs: 1000 * 60 * 60, // 1 hour session duration (defaults to 15 min)
  },
})
```

[Reference: createConfig](https://www.alchemy.com/docs/wallets/reference/account-kit/react/functions/createConfig)

***

#### Other common causes of session ending

* **Server-Side Rendering (SSR) misconfigured**
  If you're using SSR and haven't configured the provider correctly, session state can reset on the client.
  [Enable SSR and pass initial params](https://www.alchemy.com/docs/wallets/troubleshooting/ssr)

* **Ad blockers**
  Some ad blockers (especially those with aggressive cookie or storage policies) can interfere with localStorage or SDK requests, causing unexpected logouts.

* **Private/incognito mode**
  Browsers often restrict or wipe localStorage between tabs or after a short time in incognito mode. Consider warning users or designing for short session lengths in those environments.

***

#### Debugging checklist

If you're seeing repeated or sporadic logouts in production, test the behavior across:

* Browsers (Chrome, Firefox, Safari)
* Devices (desktop vs mobile)
* Browsing modes (incognito vs standard)
* With and without ad blockers