Multichain Decoding enables seamless analysis of smart contract data across multiple blockchains. With a single contract submission, users can automatically generate protocol tables across all supported EVM chains, simplifying cross-chain data access on Dune.
This feature unifies contract data views, streamlining the analysis of protocols deployed across various chains and making cross-chain insights more accessible.
Multichain decoding offers data freshness and latency comparable to regular decoding. For details on data freshness, see our data freshness page.
Here are a few examples showing how you can use multichain decoded table views to simplify your analysis. Each example includes “before” and “after” queries to demonstrate how multichain views streamline cross-chain analytics.
SELECT*FROM(SELECT--this event is emitted on sale set updates too so we take distinctdistinct 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')asbigint))),timestamp'1970-01-01')as start_time,COALESCE(try(from_unixtime(cast(json_value(salesConfig,'strict $.saleEnd')asbigint))),timestamp'2050-01-01')as end_time, l.poolAddress as uni_pool, l.evt_block_time, row_number()over(partitionby collection, erc20zAddress, tokenId orderby evt_block_time desc)as last_sale_setFROM(SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,chainAS blockchainFROM zora_multichain.ZoraTimedSaleStrategy_evt_SaleSet ) l LEFTJOIN(SELECT name, defaultAdmin, newContract,chainAS blockchainFROM zora_multichain.ZoraCreator1155FactoryImpl_evt_SetupNewContract ) nft ON l.collection = nft.newContract AND l.blockchain = nft.blockchain)WHERE last_sale_set =1
SELECT*FROM(SELECT--this event is emitted on sale set updates too so we take distinctdistinct 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')asbigint))),timestamp'1970-01-01')as start_time,COALESCE(try(from_unixtime(cast(json_value(salesConfig,'strict $.saleEnd')asbigint))),timestamp'2050-01-01')as end_time, l.poolAddress as uni_pool, l.evt_block_time, row_number()over(partitionby collection, erc20zAddress, tokenId orderby evt_block_time desc)as last_sale_setFROM(SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,chainAS blockchainFROM zora_multichain.ZoraTimedSaleStrategy_evt_SaleSet ) l LEFTJOIN(SELECT name, defaultAdmin, newContract,chainAS blockchainFROM zora_multichain.ZoraCreator1155FactoryImpl_evt_SetupNewContract ) nft ON l.collection = nft.newContract AND l.blockchain = nft.blockchain)WHERE last_sale_set =1
SELECT*FROM(SELECT--this event is emitted on sale set updates too so we take distinctdistinct 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')asbigint))),timestamp'1970-01-01')as start_time,COALESCE(try(from_unixtime(cast(json_value(salesConfig,'strict $.saleEnd')asbigint))),timestamp'2050-01-01')as end_time, l.poolAddress as uni_pool, l.evt_block_time, row_number()over(partitionby collection, erc20zAddress, tokenId orderby evt_block_time desc)as last_sale_setFROM(SELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,'zora'as blockchain FROM zora_zora.ZoraTimedSaleStrategy_evt_SaleSetUNIONALLSELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,'base'as blockchain FROM zora_base.ZoraTimedSaleStrategy_evt_SaleSetUNIONALLSELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,'optimism'as blockchain FROM zora_optimism.ZoraTimedSaleStrategy_evt_SaleSetUNIONALLSELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,'arbitrum'as blockchain FROM zora_arbitrum.ZoraTimedSaleStrategy_evt_SaleSetUNIONALLSELECT collection, erc20zAddress, tokenId, salesConfig, evt_block_time, poolAddress,'blast'as blockchain FROM zora_blast.ZoraTimedSaleStrategy_evt_SaleSet) l LEFTJOIN(SELECT name, defaultAdmin, newContract,'zora'as blockchain FROM zora_zora.ZoraCreator1155_evt_SetupNewContract UNIONALLSELECT name, defaultAdmin, newContract,'base'as blockchain FROM zora_base.ZoraCreator1155FactoryImpl_evt_SetupNewContract --different name?UNIONALLSELECT name, defaultAdmin, newContract,'optimism'as blockchain FROM zora_optimism.ZoraCreator1155FactoryImpl_evt_SetupNewContract --different name?UNIONALLSELECT name, defaultAdmin, newContract,'arbitrum'as blockchain FROM zora_arbitrum.ZoraCreator1155Factory_evt_SetupNewContract --lmao another different nameUNIONALLSELECT name, defaultAdmin, newContract,'blast'as blockchain FROM zora_blast.ZoraCreator1155FactoryImpl_evt_SetupNewContract --missing? submitted) nft ON l.collection = nft.newContract AND l.blockchain = nft.blockchain-- WHERE try(cast(json_value(salesConfig, 'strict $.saleStart') as bigint)) is null -- or try(cast(json_value(salesConfig, 'strict $.saleEnd') as bigint)) is null)WHERE last_sale_set =1
When contracts with the same ABI are submitted across multiple chains, they are combined into a single cross-chain table, enabling consistent, streamlined data access and queries across chains.
Multichain decoded contract tables are accessible in the Data Explorer, just like regular decoded contract tables. These multichain entries feature a distinct symbol and display the list of supported chains, clearly indicating they span multiple chains.