Wallets

Wallet Upgrades

Smart Contract Account (SCA) and Modular Smart Contract Account (MSCA) wallets use a contract proxy pattern, a common design pattern that allows Circle to upgrade the contract's logic without changing the address of the contract. With a proxy pattern, the proxy contract delegates calls to an implementation contract. The proxy contract can be configured to use a new implementation contract, which is commonly referred to as an upgrade. Circle uses the ERC-1967 proxy pattern, which is well-established in the crypto industry.

The proxy pattern gives Circle the ability to provide bug fixes and product improvements to SCAs and MSCAs over time. However, you are in full control of your wallets, even when Circle performs a contract upgrade. When Circle makes a new version of a contract available, you must manually initiate an upgrade using the API.

You can upgrade both developer-controlled and user-controlled SCA wallets to newer SCA versions using the Wallet Upgrade API.

Source SCA VersionDestination SCA VersionContract Function Used for Upgrade
circle_4337_v1circle_6900_singleowner_v2upgradeToAndCall(address,bytes)
circle_6900_singleowner_v1circle_6900_singleowner_v2upgradeTo(address)

After calling any Wallet Upgrade API endpoint, a transaction appears in the Developer Console UI and transaction APIs, showing the contract execution call that upgrades the wallet. Once the transaction reaches the COMPLETE state, the SCA version of the wallet is updated in the responses of the GET /wallets/{id} or GET /wallets endpoints.

Special handling for circle_4337_v1 wallets

Due to onchain specific requirements, circle_4337_v1 wallets must be lazy deployed before they can be upgraded. To trigger deployment, initiate an outbound transfer or contract execution from the SCA wallet you want to upgrade. See the Account Types page for more details on SCA lazy deployment.

If you need to upgrade a circle_4337_v1 wallet on a testnet, send native token funds to the wallet's owner address. You can retrieve the owner address using the POST /contracts/query endpoint.

response = await client.queryContract({
  abiFunctionSignature: 'owner()',
  address: '<replace-me-with-your-circle_4337_v1-sca-wallet-address>',
  blockchain: "<replace-me-with-your-wallet's-blockchain>",
  abiJson:
    '[{"inputs": [],"name": "owner","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"}]',
})

Response Body

JSON
{
  "data": {
    "outputData": "0x...",
    "outputValues": ["<owner-address>"]
  }
}

The first entry in the outputValues array contains the owner address, which must receive the native token funds. Circle recommends sending enough tokens to cover ~300,000 gas. Estimated costs:

  • ETH-SEPOLIA: 300,000 gas * 30 Gwei (replace with current gas price) = 0.009 ETH
  • MATIC-AMOY: 300,000 gas * 150 Gwei (replace with current gas price) = 0.045 POL

The wallet upgrade contract execution updates the logic contract address of the ERC-1967 proxy (the SCA wallet) by calling either:

  • upgradeTo(addresss)
  • upgradeToAndCall(addresss,bytes)

Your wallet's address and assets don't change during or after the upgrade. You can continue to use the wallet normally while the upgrade transaction is in progress.

Did this page help you?
© 2023-2025 Circle Technology Services, LLC. All rights reserved.