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

# Upgrade MEE Suite

> Complete guide to migrate to the newer version of MEE stack

# Upgrade to the newer MEE contracts

> Complete guide to migrate to the newer version of MEE stack.

<Callout type="info">
  This guide explains how to upgrade to the latest MEE contracts suite. This involves upgrading your Nexus smart accounts from older versions to the latest implementation. The migration process preserves your account's address, balance, and history while providing access to new features, security fixes, and performance improvements.
</Callout>

## Why Upgrade?

<CardGroup cols={1}>
  <Card title="Benefits of Upgrading" icon="arrow-up">
    Upgrading your Nexus smart account is recommended for several important reasons:

    <Steps>
      <Step title="Security Improvements">
        The latest implementation includes critical security enhancements.
      </Step>

      <Step title="New Features">
        Access to the newest MEE capabilities.
      </Step>

      <Step title="Performance Improvements">
        Enhanced gas efficiency and transaction processing.
      </Step>

      <Step title="Compatibility">
        Ensure you can leverage all the latest features of AbstractJS SDK and MEE infra.
      </Step>
    </Steps>
  </Card>
</CardGroup>

## Migration Process Overview

<CardGroup cols={1}>
  <Card title="Migration Steps" icon="list">
    The migration consists of these key steps:

    <Steps>
      <Step title="Update AbstractJS Package">
        Install the latest SDK version
      </Step>

      <Step title="Connect to Existing Account">
        Use your existing account address
      </Step>

      <Step title="Upgrade Implementation">
        Call `upgradeToAndCall()` via Supertransaction
      </Step>

      <Step title="Verify Upgrade">
        Test the account by executing a simple Supertransaction
      </Step>

      <Step title="Update Application">
        Adjust your application to use the latest features
      </Step>
    </Steps>
  </Card>
</CardGroup>

## Important Notes for Migration

<Callout type="warning">
  **CRITICAL**: After migration, you **must store your account address** and use it with the `accountAddress` parameter in `toNexusAccount()` or `toMultichainNexusAccount()` for all future interactions. This is how you'll maintain access to your upgraded account and its balances.
</Callout>

## Step 1: Update AbstractJS Package

<CardGroup cols={1}>
  <Card title="SDK Update" icon="download">
    First, update to the latest version of the AbstractJS SDK:

    ```bash theme={null}
    # npm
    npm update @biconomy/abstractjs

    # yarn
    yarn upgrade @biconomy/abstractjs

    # pnpm
    pnpm update @biconomy/abstractjs

    # bun
    bun update @biconomy/abstractjs
    ```
  </Card>
</CardGroup>

## Step 2: Connect to Your Existing Account

<CardGroup cols={1}>
  <Card title="Account Connection" icon="link">
    When connecting to an account created with an older SDK version, you'll need your existing account address:

    ```typescript theme={null}
      import {
        createMeeClient,
        getMEEVersion,
        MEEVersion,
        toMultichainNexusAccount,
      } from "@biconomy/abstractjs";
      import { Hex, http } from "viem";
      import { privateKeyToAccount } from "viem/accounts";
      import { base } from "viem/chains";

      const privateKey: Hex = "0xyour_private_key";
      const eoaAccount = privateKeyToAccount(privateKey);

      // Initialize mcNexus with current version config
      const mcNexus = await toMultichainNexusAccount({
        signer: eoaAccount,
        chainConfigurations: [
          {
            // Your preferred chains
            chain: base,
            // Use a reliable RPC here to avoid RPC issues
            transport: http(),
            // Use the current MEE version here
            version: getMEEVersion(MEEVersion.V2_0_0),
            // This is completely optional if this is the first time your upgrading your Smart account.
            // If you have already upgraded from some X MEE version to Y MEE version ? This field is mandatory
            accountAddress: '0xyour_sca_address',
          },
        ],
      });

      // Create MEE client
      const meeClient = await createMeeClient({
        account: mcNexus,
      });
    ```
  </Card>
</CardGroup>

<Callout type="warning">
  <strong>Note:</strong> After upgrading, use your existing <code>accountAddress</code> for all SDK operations.

  <ul>
    <li><code>accountAddress</code> is optional on your <b>first</b> upgrade.</li>
    <li>After any previous upgrade, always provide <code>accountAddress</code> to avoid errors or wrong account access.</li>
  </ul>
</Callout>

## Step 3: Upgrade the Smart Account

<CardGroup cols={1}>
  <Card title="Account Upgrade" icon="arrow-up">
    Call the `upgradeToAndCall()` method to upgrade your account to the latest implementation.

    <Tabs>
      <Tab title="Different MEE K1 Validator is used">
        In most cases, your account is going to use newer MEE K1 Validator, so you'll have to re-initialize it while upgrading the account.

        ```typescript theme={null}
            /**
            * Generate upgrade init data for Nexus account upgrade with new validator initialization
            */
            export function getUpgradeInitData(
                ownerAddress: Address,
                bootstrapAddress: Address,
              ): `0x${string}` {
                // Step 1: Encode initNexusWithDefaultValidator call with owner address
                const bootstrapCall = encodeFunctionData({
                  abi: NexusBootstrapAbi,
                  functionName: 'initNexusWithDefaultValidator',
                  args: [ownerAddress],
                });
              
                // Step 2: Package bootstrap address + call as tuple
                const bootstrapData = encodeAbiParameters(
                  [
                    { name: 'bootstrap', type: 'address' },
                    { name: 'initData', type: 'bytes' },
                  ],
                  [bootstrapAddress, bootstrapCall]
                );
              
                // Step 3: Wrap in initializeAccount call
                const upgradeInitData = encodeFunctionData({
                  abi: parseAbi(['function initializeAccount(bytes initData)']),
                  functionName: 'initializeAccount',
                  args: [bootstrapData],
                });
              
                return upgradeInitData;
              }

            // New MEE version config for account upgrades
            const newMEEVersionConfig = getMEEVersion(MEEVersion.V2_1_0);
            const newImplementationAddress = newMEEVersionConfig.implementationAddress;
            const newBootstrapAddress = newMEEVersionConfig.bootStrapAddress;

            const upgradeInitData = getUpgradeInitData(
              eoaAccount.address,
              newBootstrapAddress
            );

            const upgradeAbi = parseAbi([
              "function upgradeToAndCall(address newImplementation, bytes data)",
            ]);

            // Build composable instruction to upgrade your Nexus smart account
            const instructions = await mcNexus.buildComposable({
              type: "default",
              data: {
                // Smart account address
                to: mcNexus.addressOn(base.id, true),
                functionName: "upgradeToAndCall",
                args: [newImplementationAddress, upgradeInitData],
                abi: upgradeAbi,
                chainId: base.id,
              },
            });

            const USDC_BASE: Address = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // fee token

            const triggerAmount = 1n;

            // This example follows a fusion mode for upgrading the Nexus smart account via Supertransaction
            // If you wanted to upgrade your account via smart account mode ? Please use getQuote and executeQuote flows
            const quote = await meeClient.getFusionQuote({
              instructions,
              trigger: {
                tokenAddress: USDC_BASE,
                chainId: base.id,
                amount: triggerAmount,
              },
              feeToken: {
                address: USDC_BASE,
                chainId: base.id,
              },
              simulation: {
                simulate: true,
              },
            });

            // Executes the supertransaction
            const { hash: supertxHash } = await meeClient.executeFusionQuote({
              fusionQuote: quote,
            });

            // Wait for the supertransaction
            const receipt = await meeClient.waitForSupertransactionReceipt({
              hash: supertxHash,
            });

        ```
      </Tab>

      <Tab title="Same MEE K1 is used">
        Sometimes, your account will keep using the same validator.
        For example, if you are upgrading from MEE 1.0.0 to MEE 2.0.0
        In this case, you do not need to re-initialize the validator module.
        So just call `upgradeToAndCall()` without initData.

        ```typescript theme={null}
          const upgradeAbi = parseAbi([
            "function upgradeToAndCall(address newImplementation, bytes data)",
          ]);

          // Build composable instruction to upgrade Nexus
          const instructions = await mcNexus.buildComposable({
            type: "default",
            data: {
              // Smart account address
              to: mcNexus.addressOn(base.id, true),
              functionName: "upgradeToAndCall",
              args: [newImplementationAddress, '0x'],
              abi: upgradeAbi,
              chainId: base.id,
            },
          });

          const USDC_BASE: Address = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // fee token

          const triggerAmount = 1n;

          // This example follows a fusion mode for upgrading the Nexus smart account via Supertransaction
          // If you wanted to upgrade your account via smart account mode ? Please use getQuote and executeQuote flows
          const quote = await meeClient.getFusionQuote({
            instructions,
            trigger: {
              tokenAddress: USDC_BASE,
              chainId: base.id,
              amount: triggerAmount,
            },
            feeToken: {
              address: USDC_BASE,
              chainId: base.id,
            },
            simulation: {
              simulate: true,
            },
          });

          // Executes the supertransaction
          const { hash: supertxHash } = await meeClient.executeFusionQuote({
            fusionQuote: quote,
          });

          // Wait for the supertransaction
          const receipt = await meeClient.waitForSupertransactionReceipt({
            hash: supertxHash,
          });
        ```

        However, if you want, you may still provide initdata, which can make any additional configuration you may want at the upgrade time. For example, you may want to uninstall previously installed validators or install any additional validators you like, for example Smart Sessions.
      </Tab>
    </Tabs>
  </Card>
</CardGroup>

## Step 4: Verify the Upgrade

<CardGroup cols={1}>
  <Card title="Upgrade Verification" icon="check">
    After upgrading, verify that your account works correctly by performing a test supertransaction:

    ```typescript theme={null}
        import {
          createMeeClient,
          getMEEVersion,
          MEEVersion,
          toMultichainNexusAccount,
        } from "@biconomy/abstractjs";
        import { Address, Hex, http } from "viem";
        import { privateKeyToAccount } from "viem/accounts";
        import { base } from "viem/chains";

        const privateKey: Hex = "0xyour_private_key";
        const storedSmartAccountAddress: Address = "0xyour_sca_address";
        const eoaAccount = privateKeyToAccount(privateKey);

        // Initialize mcNexus with new version config
        const mcNexus = await toMultichainNexusAccount({
          signer: eoaAccount,
          chainConfigurations: [
            {
              chain: base,
              transport: http(),
              version: getMEEVersion(MEEVersion.V2_1_0),
              // This is essential
              accountAddress: storedSmartAccountAddress,
            },
          ],
        });

        // Create MEE client
        const meeClient = await createMeeClient({
          account: mcNexus,
        });

        const USDC_BASE: Address = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // fee token

        const amount = 1n;
        const instructions = await mcNexus.buildComposable({
          type: "transfer",
          data: {
            tokenAddress: USDC_BASE,
            chainId: base.id,
            amount,
            recipient: eoaAccount.address,
          },
        });

        // Get quotes
        const quote = await meeClient.getFusionQuote({
          instructions,
          trigger: {
            tokenAddress: USDC_BASE,
            chainId: base.id,
            amount,
          },
          feeToken: {
            address: USDC_BASE,
            chainId: base.id,
          },
        });

        // Executes the supertransaction
        const { hash: supertxHash } = await meeClient.executeFusionQuote({
          fusionQuote: quote,
        });

        // Wait for the supertransaction
        const receipt = await meeClient.waitForSupertransactionReceipt({
          hash: supertxHash,
        });
    ```
  </Card>
</CardGroup>

## Step 5: Store Your Account Address

<CardGroup cols={1}>
  <Card title="Address Storage" icon="save">
    After successful migration, you **MUST store your account address** for future use:

    ```typescript theme={null}
    // Get and store your account address
    const accountAddress = mcNexus.addressOn(base.id, true);
    console.log("IMPORTANT - Store this account address:", accountAddress);

    // In your application, store this address
    // (database, local storage, user profile, etc.)
    storeAccountAddress(userIdentifier, accountAddress);
    ```
  </Card>
</CardGroup>

## Post-Migration: Future Account Access

<CardGroup cols={1}>
  <Card title="Account Access After Migration" icon="key">
    After migration, **ALL** future interactions with your account must use the `accountAddress` parameter:

    ### CORRECT WAY

    to access your account after migration

    ```typescript theme={null}
      // CORRECT WAY to access your account after migration

      const mcNexus = await toMultichainNexusAccount({
        signer: eoaAccount,
        chainConfigurations: [
          {
            chain: base,
            transport: http(),
            version: getMEEVersion(MEEVersion.V2_1_0),
            accountAddress: "YOUR_STORED_ACCOUNT_ADDRESS" // This is essential
          },
        ],
      });
    ```

    ### INCORRECT WAY

    this will create a new account, not access your existing one

    ```typescript theme={null}
     // INCORRECT WAY - this will create a new account, not access your existing one

       const mcNexus = await toMultichainNexusAccount({
         signer: eoaAccount,
         chainConfigurations: [
           {
             chain: base,
             transport: http(),
             version: getMEEVersion(MEEVersion.V2_1_0),
             // Missing account address field
           },
         ],
       });
    ```
  </Card>
</CardGroup>

## Example Code

A minimal working migration script is available on GitHub: [Click here](https://github.com/bcnmy/mee-upgrade)

## Troubleshooting

<CardGroup cols={1}>
  <Card title="Common Issues and Solutions" icon="help">
    If you encounter issues during the migration:

    <Tabs>
      <Tab title="Upgrade Transaction Fails">
        <Steps>
          <Step title="Check Funds">
            Make sure you're re-initializing or not re-initializing the validator module depending on the version you are migrating from and to. See two tabs on the Step 3.
          </Step>

          <Step title="Check Funds">
            Ensure the account has sufficient funds for gas or use sponsorship mode for gasless upgrades
          </Step>

          <Step title="Verify Deployment">
            Verify the account is properly deployed on-chain
          </Step>

          <Step title="Check SDK Version">
            Check that your application is using the latest SDK version
          </Step>
        </Steps>
      </Tab>

      <Tab title="Cannot Access Account After Upgrade">
        <Steps>
          <Step title="Verify Address">
            Make sure you're using the correct account address in the `accountAddress` parameter
          </Step>

          <Step title="Check Transaction">
            Verify the upgrade transaction completed successfully
          </Step>

          <Step title="Confirm Address">
            Ensure you're using the exact same address as your pre-migration account
          </Step>
        </Steps>
      </Tab>
    </Tabs>
  </Card>
</CardGroup>

## Next Steps

<Callout type="success">
  After successfully migrating your Nexus account:
</Callout>

<CardGroup cols={1}>
  <Card title="Post-Migration Actions" icon="check-circle">
    <Steps>
      <Step title="Store Account Address">
        **STORE YOUR ACCOUNT ADDRESS** in your application's persistent storage
      </Step>

      <Step title="Update Application Code">
        **Update your application code** to use the `accountAddress` parameter in all future interactions
      </Step>

      <Step title="Test Thoroughly">
        **Test thoroughly** with real transactions to ensure everything works as expected
      </Step>
    </Steps>
  </Card>
</CardGroup>

<Callout type="info">
  By following this migration guide and properly storing your account address, you've successfully upgraded your Nexus account to the latest implementation while preserving its address, balance, and history.
</Callout>
