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

# Multichain Decoding

> Consolidate decoded contract data across EVM chains into unified, queryable tables.

Multichain Decoding consolidates decoded contract data across all supported EVM chains into a single table per contract. Instead of maintaining separate `UNION ALL` queries for every chain your protocol operates on, you submit once and query one table — with a `chain` column to filter or aggregate by network.

This eliminates the most common sources of broken cross-chain queries: missing a newly supported chain, inconsistent table naming across deployments, or schema drift between separate submissions.

<Info>Multichain contract submissions require a **paid team plan**. See [pricing](https://dune.com/pricing) for details.</Info>

<Tip>Multichain tables have the same data freshness and latency as single-chain decoded tables. See [data freshness](../../data-catalog/data-freshness) for SLA details.</Tip>

## Prerequisites

Before submitting a multichain contract, ensure the following:

| Requirement           | Details                                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **Identical ABI**     | Contracts must share the exact same ABI across all chains.                                                             |
| **Consistent naming** | Contracts must use the same project namespace and contract name (e.g., `uniswap_v3` / `UniswapV3Pool`).                |
| **Paid team plan**    | Multichain submissions are only available to teams on a paid subscription. [Compare plans →](https://dune.com/pricing) |

Dune uses this standardized labeling to merge data from different chains into a single cross-chain table.

## Submitting Contracts

To submit a multichain contract, use the [contract submission page](https://dune.com/contracts/new). Select **Submit on Multiple Chains**, provide the ABI, and select all target chains.

When contracts with the same ABI are submitted across multiple chains, Dune combines them into a single table — no additional configuration needed.

For detailed submission instructions — including factory contracts, proxy patterns, and bytecode matching — see the [Contract Decoding Best Practices Guide](/web-app/decoding/best-practices).

## Querying Multichain Tables

### Naming Convention

Multichain decoded tables follow the naming pattern:

```
{project}_multichain.{ContractName}_{evt|call}_{EventOrFunctionName}
```

For example:

* `gnosis_safe_multichain.Safe_v1_4_1_call_execTransaction`
* `zora_multichain.ZoraTimedSaleStrategy_evt_SaleSet`

### Schema

Each multichain table includes a `chain` column identifying the source network, alongside all standard decoded columns (`evt_block_time`, `evt_tx_hash`, `call_block_time`, etc.).

```sql theme={null}
-- All execTransaction calls on Ethereum
SELECT chain, call_block_time, call_tx_hash
FROM gnosis_safe_multichain.Safe_v1_4_1_call_execTransaction
WHERE chain = 'ethereum'
```

### Finding Tables in the Data Explorer

Multichain decoded tables are accessible in the Data Explorer alongside regular decoded tables. They display a distinct multichain icon and list all supported chains.

<img src="https://mintcdn.com/dune/6vWXO_JiAjw4C8nz/web-app/images/decoding-contracts/multichain_object_in_de.png?fit=max&auto=format&n=6vWXO_JiAjw4C8nz&q=85&s=9124e47b108b8c00d7877d647e7a10da" alt="Multichain table in Data Explorer" width="394" height="370" data-path="web-app/images/decoding-contracts/multichain_object_in_de.png" />

## Examples

The following examples compare multichain queries against the equivalent manual `UNION ALL` approach. In each case, multichain tables reduce query complexity and eliminate the need to track per-chain table names.

<Accordion title="Finding Zora Uniswap Collections">
  <Tabs>
    <Tab title="Multichain table">
      ```sql theme={null}
        SELECT * 
        FROM (
            SELECT 
                --this event is emitted on sale set updates too so we take distinct
                distinct
                l.blockchain
                , l.collection as nft_address
                , l.erc20zAddress as erc20_address
                , l.tokenId as token_id
                , nft.name as nft_collection_name
                , nft.defaultAdmin as creator
                , json_value(salesConfig, 'strict $.name') as nft_name
                , json_value(salesConfig, 'strict $.symbol') as nft_symbol
                , COALESCE(try(from_unixtime(cast(json_value(salesConfig, 'strict $.saleStart') as bigint))),timestamp '1970-01-01') as start_time
                , COALESCE(try(from_unixtime(cast(json_value(salesConfig, 'strict $.saleEnd') as bigint))),timestamp '2050-01-01') as end_time
                , l.poolAddress as uni_pool
                , l.evt_block_time
                , row_number() over (partition by collection, erc20zAddress, tokenId order by evt_block_time desc) as last_sale_set
            FROM ( SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, chain AS blockchain
                  FROM zora_multichain.ZoraTimedSaleStrategy_evt_SaleSet ) l 
            LEFT JOIN ( SELECT name, defaultAdmin, newContract, chain AS blockchain
                        FROM zora_multichain.ZoraCreator1155FactoryImpl_evt_SetupNewContract ) nft 
                  ON l.collection = nft.newContract AND l.blockchain = nft.blockchain
        ) 
        WHERE last_sale_set = 1
      ```
    </Tab>

    <Tab title="Manual UNION ALL (per-chain)">
      ```sql theme={null}
        SELECT 
        * 
        FROM (
            SELECT 
                --this event is emitted on sale set updates too so we take distinct
                distinct
                l.blockchain
                , l.collection as nft_address
                , l.erc20zAddress as erc20_address
                , l.tokenId as token_id
                , nft.name as nft_collection_name
                , nft.defaultAdmin as creator
                , json_value(salesConfig, 'strict $.name') as nft_name
                , json_value(salesConfig, 'strict $.symbol') as nft_symbol
                , COALESCE(try(from_unixtime(cast(json_value(salesConfig, 'strict $.saleStart') as bigint))),timestamp '1970-01-01') as start_time
                , COALESCE(try(from_unixtime(cast(json_value(salesConfig, 'strict $.saleEnd') as bigint))),timestamp '2050-01-01') as end_time
                , l.poolAddress as uni_pool
                , l.evt_block_time
                , row_number() over (partition by collection, erc20zAddress, tokenId order by evt_block_time desc) as last_sale_set
            FROM (
                SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, 'zora' as blockchain FROM zora_zora.ZoraTimedSaleStrategy_evt_SaleSet
                UNION ALL
                SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, 'base' as blockchain FROM zora_base.ZoraTimedSaleStrategy_evt_SaleSet
                UNION ALL
                SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, 'optimism' as blockchain FROM zora_optimism.ZoraTimedSaleStrategy_evt_SaleSet
                UNION ALL
                SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, 'arbitrum' as blockchain FROM zora_arbitrum.ZoraTimedSaleStrategy_evt_SaleSet
                UNION ALL
                SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress, 'blast' as blockchain FROM zora_blast.ZoraTimedSaleStrategy_evt_SaleSet
            ) l 
            LEFT JOIN (
                SELECT name, defaultAdmin, newContract, 'zora' as blockchain FROM zora_zora.ZoraCreator1155_evt_SetupNewContract 
                UNION ALL 
                SELECT name, defaultAdmin, newContract, 'base' as blockchain FROM zora_base.ZoraCreator1155FactoryImpl_evt_SetupNewContract
                UNION ALL  
                SELECT name, defaultAdmin, newContract, 'optimism' as blockchain FROM zora_optimism.ZoraCreator1155FactoryImpl_evt_SetupNewContract
                UNION ALL 
                SELECT name, defaultAdmin, newContract, 'arbitrum' as blockchain FROM zora_arbitrum.ZoraCreator1155Factory_evt_SetupNewContract
                UNION ALL 
                SELECT name, defaultAdmin, newContract, 'blast' as blockchain FROM zora_blast.ZoraCreator1155FactoryImpl_evt_SetupNewContract
            ) nft ON l.collection = nft.newContract AND l.blockchain = nft.blockchain
        ) 
        WHERE last_sale_set = 1
      ```
    </Tab>
  </Tabs>
</Accordion>

<Accordion title="Gnosis Safe `execTransaction` Calls">
  <Tabs>
    <Tab title="Multichain table">
      ```sql theme={null}
        select chain, date_trunc('day', call_block_time) AS block_date, count(*) as cnt
        from gnosis_safe_multichain.Safe_v1_4_1_call_execTransaction
        group by 1, 2
      ```
    </Tab>

    <Tab title="Manual UNION ALL (per-chain)">
      ```sql theme={null}
        select chain, date_trunc('day', call_block_time) AS block_date, count(*) as cnt
        from (
        SELECT 'arbitrum' AS chain, call_block_time
        FROM gnosis_safe_arbitrum.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'avalanche_c' AS chain, call_block_time
        FROM gnosis_safe_avalanche_c.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'blast' AS chain, call_block_time
        FROM gnosis_safe_blast.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'base' AS chain, call_block_time
        FROM gnosis_safe_base.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'bnb' AS chain, call_block_time
        FROM gnosis_safe_bnb.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'celo' AS chain, call_block_time
        FROM gnosis_safe_celo.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'ethereum' AS chain, call_block_time
        FROM gnosis_safe_ethereum.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'gnosis' AS chain, call_block_time
        FROM gnosis_safe_gnosis.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'linea' AS chain, call_block_time
        FROM gnosis_safe_linea.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'optimism' AS chain, call_block_time
        FROM gnosis_safe_optimism.Safe_v1_4_1_call_execTransaction

        UNION ALL

        SELECT 'polygon' AS chain, call_block_time
        FROM gnosis_safe_polygon.Safe_v1_4_1_call_execTransaction
        )
        group by 1,2
      ```
    </Tab>
  </Tabs>
</Accordion>
