Complete guide to migrate to the newer version of MEE stack.
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.
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.
When connecting to an account created with an older SDK version, you’ll need your existing account address:
Copy
Ask AI
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, });
Note: After upgrading, use your existing accountAddress for all SDK operations.
accountAddress is optional on your first upgrade.
After any previous upgrade, always provide accountAddress to avoid errors or wrong account access.
Call the upgradeToAndCall() method to upgrade your account to the latest implementation.
Different MEE K1 Validator is used
Same MEE K1 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.
Copy
Ask AI
/** * 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, });
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.
Copy
Ask AI
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.
After successful migration, you MUST store your account address for future use:
Copy
Ask AI
// Get and store your account addressconst 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);
this will create a new account, not access your existing one
Copy
Ask AI
// 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 }, ], });
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.
2
Check Funds
Ensure the account has sufficient funds for gas or use sponsorship mode for gasless upgrades
3
Verify Deployment
Verify the account is properly deployed on-chain
4
Check SDK Version
Check that your application is using the latest SDK version
1
Verify Address
Make sure you’re using the correct account address in the accountAddress parameter
2
Check Transaction
Verify the upgrade transaction completed successfully
3
Confirm Address
Ensure you’re using the exact same address as your pre-migration account
STORE YOUR ACCOUNT ADDRESS in your application’s persistent storage
2
Update Application Code
Update your application code to use the accountAddress parameter in all future interactions
3
Test Thoroughly
Test thoroughly with real transactions to ensure everything works as expected
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.