LayerZeroFault
ai agents-api

Fix: Wagmi CLI Foundry Plugin Multiple Addresses with Same ABI

VV

Written by

Fact-Checked on July 21, 2026

Verified Expert

Fix: Wagmi CLI Foundry Plugin Multiple Addresses with Same ABI

When building decentralized applications on Ethereum and EVM-compatible chains, developers frequently deploy multiple instances of the same contract blueprint. Whether you are launching dozens of ERC-20 token wrappers, NFT edition contracts, or independent vault instances, these deployments share the exact same ABI (Abstract Binary Interface) but reside at different contract addresses.

If you are using the @wagmi/cli tool along with its @wagmi/cli/plugins/foundry plugin, you will quickly hit a limitation: the Foundry plugin automatically scans your compiler artifacts and maps each Solidity contract name to a single generated React hook namespace. Trying to associate multiple addresses on the same chain with a single contract entry in your configuration file will result in JavaScript compilation failures or overwrite collisions.

Below, we detail how to resolve this limitation using two production-grade patterns.

If your compilation fails due to conflicting types or dependencies during this process, read our companion guide on Fixing Wagmi Foundry Plugin ABI Mismatch ERESOLVE Errors to align your build configurations.


The Problem: Solidity File-Name Key Collisions

In a standard wagmi.config.ts setup, the Foundry plugin is configured to inspect your project’s root files and automatically generate output hooks:

// wagmi.config.ts - COLLISION PRONE SETUP
import { defineConfig } from '@wagmi/cli'
import { foundry } from '@wagmi/cli/plugins'

export default defineConfig({
  out: 'src/generated.ts',
  plugins: [
    foundry({
      project: '../contracts',
      // If we attempt to map multiple addresses to a single compiled artifact,
      // the key mapping overrides itself on the same chain ID.
      deployments: {
        ZoraNFT: {
          1: '0xAddressOne',
          // 1: '0xAddressTwo' <-- SyntaxError: Duplicate object key
        }
      }
    }),
  ],
})

Because the Foundry plugin generates TypeScript code matching the exact structure of your compiled files, the generated hooks (like useReadZoraNft) expect to either have a single hardcoded address or none at all.


The cleanest, most architectural way to handle multiple contract deployments of the same ABI is to omit the address from the build configuration entirely.

If you do not define an address in the configuration, the Wagmi CLI generates generic “factory” hooks. These hooks require the target address as an input parameter whenever they are called on the frontend.

Wagmi CLI Shared ABI Compilation Flow Diagram

Step 1: Configure the CLI without Addresses

Modify your wagmi.config.ts to output the ABI and hooks without binding them to any specific address:

import { defineConfig } from '@wagmi/cli'
import { foundry } from '@wagmi/cli/plugins'

export default defineConfig({
  out: 'src/generated.ts',
  plugins: [
    foundry({
      project: '../contracts',
      // No deployments block is declared here for ZoraNFT
    }),
  ],
})

Step 2: Pass the Address Dynamically in React

When you call the generated hook in your application, you supply the address as an option. This allows a single hook to interact with an infinite number of deployed contract instances:

import { useReadZoraNft } from '../generated'

export function NFTDisplay({ tokenAddress }: { tokenAddress: `0x${string}` }) {
  // Pass the target address at runtime
  const { data: name, isLoading } = useReadZoraNft({
    address: tokenAddress,
    functionName: 'name',
  })

  if (isLoading) return <div>Loading metadata...</div>
  return <div>Contract Name: {name}</div>
}

This pattern is highly recommended because it keeps your generated TypeScript files extremely lightweight and decouples your frontend logic from hardcoded deployment addresses.


Solution 2: The Shared ABI Aliased Contracts Pattern

If you prefer to have named, hardcoded references for key contracts (for example, if you have a GoldToken and a SilverToken that are both instances of the same ERC20.sol template), you can manually define separate objects in the contracts array.

By importing the ABI JSON file compiled by Foundry directly, you can create multiple unique configurations that share the same underlying ABI.

Placeholder: Wagmi CLI Configuration for Aliased Contracts

Step 1: Map Aliased Configurations

Configure your wagmi.config.ts as follows:

import { defineConfig } from '@wagmi/cli'
import { react } from '@wagmi/cli/plugins'
// Import the ABI JSON compiled by Foundry
import ZoraNFTArtifact from '../contracts/out/ZoraNFT.sol/ZoraNFT.json' assert { type: 'json' }

export default defineConfig({
  out: 'src/generated.ts',
  contracts: [
    {
      name: 'ZoraNFTMain',
      abi: ZoraNFTArtifact.abi as any,
      address: {
        1: '0xAddressOne',
        11155111: '0xAddressOneSepolia',
      },
    },
    {
      name: 'ZoraNFTEditionTwo',
      abi: ZoraNFTArtifact.abi as any,
      address: {
        1: '0xAddressTwo',
        11155111: '0xAddressTwoSepolia',
      },
    },
  ],
  plugins: [
    react(), // Generate hooks for the contracts array
  ],
})

Step 2: Use Named Hooks in Components

The Wagmi CLI will generate unique, dedicated hooks for each named entry, making it clear which deployment is being targeted:

import { useReadZoraNftMain, useReadZoraNftEditionTwo } from '../generated'

export function Dashboard() {
  const { data: nameMain } = useReadZoraNftMain({ functionName: 'name' })
  const { data: nameEdition } = useReadZoraNftEditionTwo({ functionName: 'name' })

  return (
    <div>
      <p>Main Hub: {nameMain}</p>
      <p>Edition Two: {nameEdition}</p>
    </div>
  )
}

Summary of Best Practices

  • Use Solution 1 (Runtime Address) if the list of addresses is dynamic, large, or fetched from a database/index.
  • Use Solution 2 (Shared ABI Aliases) if you only have a few key static deployments and want type safety with pre-bound addresses.
  • Never try to duplicate keys inside the deployments mapping block of the @wagmi/cli/plugins/foundry plugin.
Partner Spotlight: Gate.io

Trade Securely on Gate.io

Don't risk your assets on centralized silos or unverified endpoints. Trade securely on Gate.io with deep liquidity and institutional-grade security protocols.

Claim $100 Sign-up Bonus

Official Partner Referral Link

Related Inquiries

Why does the Wagmi CLI Foundry plugin fail when I map multiple addresses to one contract?

The Wagmi CLI Foundry plugin auto-generates entries based on solidity file names. Because each entry must have a unique identifier in the generated bundle, defining the same contract name with multiple addresses on the same network causes JavaScript key collisions or generates duplicate bindings.

What is the Runtime Address Hook pattern?

This is a configuration pattern where you omit the 'address' property from the contract schema inside 'wagmi.config.ts'. This instructs the Wagmi CLI to generate hooks that accept a dynamic 'address' argument at runtime, allowing you to pass any matching deployment address.

How do I hardcode multiple named contracts that share the same ABI?

You can import the compiled ABI JSON file directly from your Foundry artifacts folder (e.g. 'out/MyContract.sol/MyContract.json') and list them as separate contract configurations in the 'contracts' array with unique names.