The first iteration of account abstraction from Dynamic uses ZeroDev and embedded wallets. This guide will walk you through settting up ZeroDev and Dynamic so that you can sponsor transactions on Polygon Amoy.

Initial setup

1

ZeroDev Account

Sign up for a free account at https://dashboard.zerodev.app/ and create a project, configure your project name and network (please use Polygon Amoy for this example) and copy your new ZeroDev project ID.
Note that the network you select in your ZeroDev project will be the network that the smart contract wallet is deployed on and cannot be changed without creating a new project. For this guide, we will be using Polygon Amoy.
2

Enable in Dynamic

In the EVM section of your Dynamic Dashboard, toggle on Polygon Amoy and click Save.Now, go to the Account Abstraction section, enable ZeroDev and paste in your ZeroDev project id.
3

Adding Multichain Providers (if desired)

You must be using at least SDK version 3.3.0 or 4.0.0-alpha.8 to have access to this feature
Click on “Add another chain”. You can input 1 ZeroDev project ID per chain you would like enabled.
If you would like to remove a multichain ZeroDev provider, hover your mouse over the network icon and you should be able to click the “Trash icon” to remove.
Click “Yes” to save and add another provider if desired.
4

Choose who gets a SCW

On the same configuration page as the step above, you’ll see there are two different types of configuration for issuing smart contract wallets (SCWs) in Dynamic - the wallet level and the user level.
  • Wallet level
Choose whether to issue SCWs to all wallets, or only to embedded wallets. Note that for the former, you will need to handle the UI and frontend yourself.
  • User level
Choose whether to issues SCWs to all your users (existing included next time they log in), or just new users.
5

Choose if your users see both the signer and smart wallet

On the same configuration page as the 2 steps above, you’ll see there is a setting for how the Dynamic SDK treats the signer and the smart wallet - only the smart wallet or both the smart wallet and signer.
  • Show Smart Wallet Only
Only allows you to interact with the smart wallet directly.
  • Show Smart Wallet & Signer
Treats the smart wallet and signer as separate wallets which you can switch between.
6

Enable Dynamic-powered embedded wallets + Email

Back in your Dynamic Dashboard, go to the Embedded Wallets section and enable Dynamic-powered embedded wallets.Lastly, in the Log in & User Profile section, enable Email sign up (optionally, enable social sign up and configure oauth)
Note that we currently only create smart wallets for embedded wallets. You will see native web3 wallets in your Dynamic widget, and can still use one to sign in, but only new embedded wallets will have a smart wallet.
7

Render Dynamic

In your local React project, install the following packages:
  • @dynamic-labs/sdk-react-core
  • @dynamic-labs/ethereum-aa
  • @dynamic-labs/ethereum
Then import and add the ZeroDevSmartWalletConnectors and EthereumWalletConnectors to the walletConnectors prop on DynamicContextProvider.
To use ZeroDev v5.2, use Dynamic SDK version ^2.0.5
  import { DynamicContextProvider, DynamicWidget } from "@dynamic-labs/sdk-react-core";
  import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";
  import { ZeroDevSmartWalletConnectors } from "@dynamic-labs/ethereum-aa";

  const App = () => (
    <DynamicContextProvider
      settings={{
        environmentId: "YOUR_ENVIRONMENT_ID",
        walletConnectors: [
          EthereumWalletConnectors,
          ZeroDevSmartWalletConnectors
        ],
      }}
    >
      <DynamicWidget />
    </DynamicContextProvider>
  )

  export default App;
Make sure to grab your Dynamic environment id from from the Dynamic Dashboard under Developer > SDK & API Keys, and replace it in the environmentID setting.
8

Set up a gas sponsorship rule

Now we will set up a basic gas sponsorship policy in the ZeroDev dashboardIn the Gas Policies tab, click on the button labeled “New” in the Project Policies section
Select “Amount” as the Type, “10” as the value and “Day” as the interval. This is saying that we will sponsor up to 10 MATIC total per day
Click Create Project Policy, and that’s it! Now start your app, log in and try sending some MATIC out. The Dynamic SDK will check if a transaction meets your gas policies and will automatically hide the gas in the transaction confirmation step if the gas is sponsored, if not the gas will be displayed.
Since you will be creating a brand new wallet when you log in, you will have to first send some MATIC to this address. You can access a free MATIC faucet here: https://www.alchemy.com/faucets/polygon-amoy
9

Send a transaction

Run your app, and if you copied our snippet from earlier, you should see this basic pageClick Connect your wallet, enter your email and hit Continue. After pasting in your OTP you’ll be fully logged in!Next, we’re going to send a transaction. To do that, we will need some MATIC. Grab your wallet address by clicking on the Dynamic Widget, then click on the three dots next to your address and hit “Copy wallet address”. You can paste your address into free Polygon Amoy faucet which will deposit some free test MATIC into your account. After doing so, if you refresh your app, you should see your balance update
Optionally, set up fiat onramp by following our guide here: https://docs.dynamic.xyz/fiat-onboarding/banxa
Now, send yourself some MATIC by clicking on the Send button in the Dynamic Widget. Enter 0.1 as the amount, and an addres of your choosing as the recipient, then hit Send now. You will see a screen like the following. Notice that there is no gas estimate field, because this transaction will be sponsored!Hit confirm, sign for the transaction with your passkey. Congratulations, you just sent a gas-sponsored transaction! If you take your smart wallet address and paste it into the Polygon Amoy scanner, you will see your smart wallet and the transaction you just sent.

Advanced Configuration

Now you are set up, you can utilize the full functionality of ZeroDev inside Dynamic - everything from session keys to gas policies. Learn more in the ZeroDev Docs.

Specifying a bundler/paymaster RPC

Use ZeroDevSmartWalletConnectorsWithConfig and pass in values for bundlerRpc and paymasterRpc:
import { ZeroDevSmartWalletConnectorsWithConfig } from "@dynamic-labs/ethereum-aa";

<DynamicContextProvider
  settings={{
    environmentId: "YOUR_ENV_ID",
    walletConnectors: [
      ZeroDevSmartWalletConnectorsWithConfig({
        bundlerRpc: "CUSTOM_BUNDLER_RPC",
        paymasterRpc: "CUSTOM_PAYMASTER_RPC",
      }),
    ],
  }}
>
  {/* ... your app */}
</DynamicContextProvider>;
For more info, see: https://docs.zerodev.app/sdk/infra/pimlico#using-pimlico-paymaster

Specifying a bundler

To specify a bundler, use ZeroDevSmartWalletConnectorsWithConfig and pass in a value for bundlerProvider:
import { ZeroDevSmartWalletConnectorsWithConfig } from "@dynamic-labs/ethereum-aa";

<DynamicContextProvider
  settings={{
    environmentId: "YOUR_ENV_ID",
    walletConnectors: [
      ZeroDevSmartWalletConnectorsWithConfig({ bundlerProvider: "STACKUP" }),
    ],
  }}
>
  {/* ... your app */}
</DynamicContextProvider>;
For more info, see: https://docs.zerodev.app/meta-infra/rpcs#bundler—paymaster-rpcs

Retrieving the Kernel Client using getAccountAbstractionProvider()

import { isZeroDevConnector } from '@dynamic-labs/ethereum-aa';

const App = () => {
  const { primaryWallet } = useDynamicContext();

  useEffect(() => {
    const { connector } = primaryWallet;

    if (isZeroDevConnector(connector)) {
      const params = {
        // if you have gas sponsorship enabled, set `withSponsorship` to `true`, else omit
        withSponsorship: true
      };
      const kernelClient = connector.getAccountAbstractionProvider(params);
    }
  }, [primaryWallet]);

  ...
}

Using with Viem & Ethers

You can use viem or ethers with account abstraction to sign messages or send sponsored transaction with no extra configuration, it also works with our wagmi integration.

Going Further

Once you’ve tested things out and want to deploy to a live network, you will need to do the following:
  1. Add your credit card to ZeroDev under Account Settings > Billing
  2. Create a new ZeroDev project and select a live network
  3. Copy your new ZeroDev project id and paste it into your Dynamic Dashboard a. We recommend using your Dynamic Sandbox environment for testing your testnet setup, and using your Dynamic Live environment for production.

Restricting Access to your ZeroDev Project

In order to restrict access to your ZeroDev project id to allow only dynamic to use it you can add dynamic’s static IP address’s to your projects IP allowlist. Dynamic’s IP addresses:
  • 52.204.85.87
  • 54.145.74.8
  • 107.20.170.238
  • 52.206.26.56
  • 3.232.2.67
  • 44.213.187.169

Examples

Get smart wallet address vs signer address

The wallet connector will return your smart wallet address, that address will be used in the Dynamic UI and is the main address you will interact with. But you can fetch the signer address by using the wallet connector getEOAConnector and then fetching the address there.
import { useEffect, useState } from "useEffect";
import {
  useDynamicContext,
  DynamicContextProvider,
  DynamicWidget,
} from "@dynamic-labs/sdk-react-core";
import {
  isZeroDevConnector,
  ZeroDevSmartWalletConnectors,
} from "@dynamic-labs/ethereum-aa";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";

const SignerAddress = () => {
  const { primaryWallet } = useDynamicContext();
  const [signerAddress, setSignerAddress] = useState();

  useEffect(() => {
    if (!primaryWallet) {
      return;
    }

    const {
      connector,
      address, // This is your smart wallet address
    } = primaryWallet;

    if (!isZeroDevConnector(connector)) {
      return;
    }

    const signerConnector = connector.getEOAConnector();

    if (!signerConnector) {
      return;
    }

    // This is the signer address
    const [address] = signerConnector.getAddress();

    setSignerAddress(address);
  }, [primaryWallet]);

  return <span>My Signer address: {signerAddress}</span>;
};

const App = () => (
  <DynamicContextProvider
    settings={{
      environmentId: "YOUR_ENVIRONMENT_ID",
      walletConnectors: [
        EthereumWalletConnectors,
        ZeroDevSmartWalletConnectors,
      ],
    }}
  >
    <DynamicWidget />

    <SignerAddress />
  </DynamicContextProvider>
);

export default App;
For more information about ZeroDev’s AA features, go to ZeroDev’s documentation: https://docs.zerodev.app/

FAQ

Yes, but not today with Dynamic. We are working on developing new flows to make managing existing EOA wallets with SCWs a smooth transition.
It depends which provider you choose. For example, with ZeroDev you have the following options:
  • Arbirtrum One
  • Avalanche
  • Base
  • Binance Smart Chain
  • Eth
  • Optimism
  • Polygon
Each provider will handle things differently, so it’s always better to check directly with them. For example, with ZeroDev you can’t change the network after deployment. With Alchemy, it might be possible in a roundabout way.
With Dynamic, you will need to use either ZeroDev or Alchemy. If you have alternative AA providers, please reach out via our slack.
This is an advanced feature, but there is no additional cost from Dynamic beyond the advanced tier itself. The providers do take a transaction fee, which you can see on their respective pricing pages.
We are adding customers one at a time for a few weeks, after which we’ll open it up to the general public as GA.
Private keys are managed by the EOA, not the SCW. Every SCW has a Signer, or Owner, which is the EOA.
The only way the SCW can be recovered is if the EOA is recovered. The SCW is a smart contract, and the EOA is the owner of the SCW. If the EOA is lost, the SCW is lost.
It’s a common misconception that AA wallets are inherently non-custodial. In fact, whether a wallet is AA or not has nothing to do with whether it’s custodial. It’s the signers that determine whether a wallet is custodial.That is, if you use a non-custodial signer such as local private keys to manage your AA wallet, then it’s non-custodial. At the same time, if you use a custodial key provider such as Fireblocks to manage your AA wallet, then it’s custodial.In any case, whoever has custody over the signers has custody over the wallet.
We have wrapped our providers so you get all the benefit, and more. For example, we handle the transaction hashing so it’s user friendly and are able to show the SCW in our widgets and connectors.