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

# Deployed Endpoints, Message Libraries, and Executors

> Learn about Deployed Endpoints, Message Libraries, and Executors in LayerZero V2. Understand the architecture, core concepts, and how it enables omnichain in...

export const ContractAddressesTable = ({version = 2}) => {
  const safeString = str => (str || '').toString();
  const safeLower = str => safeString(str).toLowerCase();
  const getExplorerUrl = deployment => {
    const chainKey = safeString(deployment?.chainKey);
    return `https://layerzeroscan.com/api/explorer/${chainKey}/address`;
  };
  const isTonDeployment = deployment => {
    const chainKey = safeLower(deployment?.chainKey);
    return chainKey === 'ton';
  };
  const isSolanaDeployment = deployment => {
    const chainKey = safeLower(deployment?.chainKey);
    return ['solana', 'solana-testnet'].includes(chainKey);
  };
  var notesMap = {
    "273": "The Skale Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify LzApp to handle ERC20 fees.",
    "385": "The Dinari Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify LzApp to handle ERC20 fees.",
    "10285": "The Hedera EVM has 8 decimals while their JSON RPC uses 18 decimals for `msg.value`, please take precaution when calling `quoteFee`",
    "30154": "The Ethereum Sepolia Mainnet Endpoint is a connection between Sepolia Testnet and LayerZero Mainnet Endpoints. This should NOT be used for testing connections to other testnet networks.",
    "30165": "zkSync uses its own compiler called zkSync-solc, which generates different bytecode than the standard Solidity compiler (solc).",
    "30230": "Shimmer, while being EVM-like, uses a different approach to gas token decimals, which could lead to specific implementations and adjustments in your gas calculations and transactions.",
    "30265": "The Homeverse Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify your _payNative() function in OApp to handle ERC20 fees (see OFTAlt).",
    "30273": "The Skale Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify your _payNative() function in OApp to handle ERC20 fees (see OFTAlt).",
    "30280": "Sei raised the SSTORE opcode gas cost from 20,000 to 72,000. Any transaction that writes to storage on Sei now costs more gas, including lzReceive calls. If your OApp hardcodes gas limits in enforced options for messages to Sei, increase them by at least 55,000 from the default 80,000 or transactions will revert. Frontends using estimateGas are unaffected, but review any fixed gas values in your on-chain or off-chain configs.",
    "30301": "zkLink uses a unique compiler designed for zero-knowledge proof generation which generates different bytecode than the standard Solidity compiler (solc).",
    "30385": "The Dinari Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify your _payNative() function in OApp to handle ERC20 fees (see OFTAlt).",
    "30390": "Monad charges users based on the gas limit specified in the transaction, not the actual gas used (https://docs.monad.xyz/developer-essentials/gas-pricing#gas-limit-not-gas-used). Additionally, Monad has repriced certain opcodes for cold state access - cold account access costs 10,100 gas (vs 2,600 on Ethereum) and cold storage access costs 8,100 gas (vs 2,100 on Ethereum) (https://docs.monad.xyz/developer-essentials/opcode-pricing). Developers should estimate gas costs for Monad transactions beforehand and set enforcedOptions with appropriately higher gas limits to account for these differences.",
    "30398": "MegaETH uses a multidimensional gas model (https://docs.megaeth.com/megaevm#multidimensional-gas-model), there are two gas costs associated with any given transaction - compute gas and storage gas. What this means for developers is that you should estimate the gas costs for MegaETH transactions beforehand and make sure you set enforcedOptions with the estimated amount + some buffer. As per our calculations - 250k gas should be sufficient.",
    "30420": "TRX, the native token of Tron, uses 6 decimals, which affects how transactions and gas fees are calculated and can require specific handling in smart contracts and dApps.",
    "40161": "LayerZero Testnet Endpoints use the real Mainnet pricefeed for cross-chain transfers. That means Ethereum Sepolia uses the real Ethereum gwei price. For testing EVM <> EVM transfers, it may be cheaper to use another EVM testnet with a cheaper cost of blockspace.",
    "40265": "The Homeverse Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees. You will need to modify your _payNative() function in OApp to handle ERC20 fees (see OFTAlt).",
    "40273": "The Skale Endpoint uses an alternative ERC20 token instead of the native gas token for omnichain fees.  You will need to modify your _payNative() function in OApp to handle ERC20 fees (see OFTAlt).",
    "40283": "zkLink uses a unique compiler designed for zero-knowledge proof generation which generates different bytecode than the standard Solidity compiler (solc).",
    "40285": "The Hedera EVM has 8 decimals while their JSON RPC uses 18 decimals for `msg.value`, please take precaution when calling `quoteFee`",
    "40305": "zkSync uses its own compiler called zkSync-solc, which generates different bytecode than the standard Solidity compiler (solc).",
    "40420": "TRX, the native token of Tron, uses 6 decimals, which affects how transactions and gas fees are calculated and can require specific handling in smart contracts and dApps."
  };
  const [isDark, setIsDark] = useState(false);
  const [deploymentsData, setDeploymentsData] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const [selectedStage, setSelectedStage] = useState(['mainnet']);
  const [selectedChains, setSelectedChains] = useState([]);
  const [showRecentlyAdded, setShowRecentlyAdded] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [isChainsListOpen, setIsChainsListOpen] = useState(false);
  const [copiedAddress, setCopiedAddress] = useState(null);
  const [failedIcons, setFailedIcons] = useState({});
  const [chainlistRPCs, setChainlistRPCs] = useState([]);
  const [isMobile, setIsMobile] = useState(false);
  const searchContainerRef = useRef(null);
  const nonEvmChains = ['solana', 'solana-testnet', 'aptos', 'aptos-testnet', 'ton', 'movement', 'movement-testnet', 'sui', 'sui-testnet', 'initia', 'initia-testnet'];
  const isEvmChain = function (chainKey) {
    var key = (chainKey || '').toString().toLowerCase();
    return !nonEvmChains.some(function (nc) {
      return key === nc || key.startsWith(nc + '-');
    });
  };
  const getQuickstartUrl = function (deployment) {
    if (!deployment) return null;
    var chainKey = (deployment.chainKey || '').toString().toLowerCase();
    var stage = deployment.stage || 'mainnet';
    var baseKey = chainKey.replace(/-(testnet|mainnet)$/i, '');
    var identifier = baseKey + '-' + stage;
    return '/v2/deployments/evm-chains/' + identifier + '-oft-quickstart';
  };
  const addToMetaMask = function (deployment) {
    if (typeof window === 'undefined' || !window.ethereum) {
      console.log('MetaMask not detected');
      return;
    }
    var chainId = deployment.nativeChainId;
    var chainRpc = chainlistRPCs.find(function (c) {
      return c.chainId === chainId;
    });
    if (!chainRpc) {
      console.log('RPC not available for chain:', chainId);
      return;
    }
    var rpcUrls = Array.isArray(chainRpc.rpc) ? chainRpc.rpc : [chainRpc.rpc];
    var params = {
      chainId: '0x' + chainId.toString(16),
      chainName: chainRpc.name || deployment.chainDisplayName,
      rpcUrls: rpcUrls,
      nativeCurrency: chainRpc.nativeCurrency || ({
        name: 'Ether',
        symbol: 'ETH',
        decimals: 18
      }),
      blockExplorerUrls: chainRpc.explorers ? chainRpc.explorers.map(function (e) {
        return e.url;
      }) : []
    };
    window.ethereum.request({
      method: 'eth_requestAccounts'
    }).then(function () {
      return window.ethereum.request({
        method: 'wallet_addEthereumChain',
        params: [params]
      });
    }).then(function () {
      console.log('Network added successfully');
    }).catch(function (err) {
      console.error('Error adding network:', err);
    });
  };
  const getInitials = function (name) {
    if (!name) return '?';
    var words = name.toString().split(' ');
    if (words.length === 1) {
      return name.slice(0, 2).toUpperCase();
    }
    return (words[0].charAt(0) + words[1].charAt(0)).toUpperCase();
  };
  const renderNetworkIcon = function (chainKey, displayName, size) {
    var iconSize = size || 22;
    var iconKey = chainKey;
    if (iconKey && (/^0g/i).test(iconKey)) {
      iconKey = iconKey.replace(/^0g/i, 'og');
    }
    var failCount = failedIcons[chainKey] || 0;
    var iconUrls = ['https://icons-ckg.pages.dev/lz-scan/networks/' + iconKey + '.svg', 'https://icons-ckg.pages.dev/lz-scan/networks/default.svg'];
    if (failCount >= iconUrls.length) {
      return <div style={{
        width: iconSize,
        height: iconSize,
        minWidth: iconSize,
        borderRadius: '50%',
        background: 'linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: Math.max(8, iconSize * 0.4),
        fontWeight: 600,
        color: '#fff',
        flexShrink: 0,
        alignSelf: 'center'
      }}>
          {getInitials(displayName || chainKey)}
        </div>;
    }
    var iconUrl = iconUrls[failCount];
    var imgStyle = {
      width: '100%',
      height: '100%',
      borderRadius: '50%',
      objectFit: 'contain'
    };
    if (!isDark) {
      imgStyle.filter = 'invert(1) brightness(1.15) contrast(1)';
    }
    return <div style={{
      width: iconSize,
      height: iconSize,
      minWidth: iconSize,
      borderRadius: '50%',
      backgroundSize: 'contain',
      backgroundRepeat: 'no-repeat',
      backgroundPosition: 'center',
      flexShrink: 0,
      position: 'relative',
      alignSelf: 'center'
    }}>
        <img src={iconUrl} alt="" style={imgStyle} onError={function () {
      setFailedIcons(function (prev) {
        var next = {};
        for (var k in prev) next[k] = prev[k];
        next[chainKey] = (prev[chainKey] || 0) + 1;
        return next;
      });
    }} />
      </div>;
  };
  const handleCopy = async (text, key, e) => {
    if (e) {
      e.preventDefault();
      e.stopPropagation();
    }
    try {
      await navigator.clipboard.writeText(text);
      setCopiedAddress(key);
      setTimeout(() => setCopiedAddress(null), 2000);
    } catch (err) {
      console.error('Failed to copy:', err);
    }
  };
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const handleResize = () => setIsMobile(window.innerWidth <= 800);
    handleResize();
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  useEffect(() => {
    if (typeof document === 'undefined') return;
    const checkTheme = () => {
      setIsDark(document.documentElement.classList.contains('dark'));
    };
    checkTheme();
    const observer = new MutationObserver(checkTheme);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => observer.disconnect();
  }, []);
  useEffect(() => {
    fetch('https://chainid.network/chains.json').then(function (r) {
      return r.json();
    }).then(function (data) {
      if (Array.isArray(data)) {
        setChainlistRPCs(data);
      }
    }).catch(function (err) {
      console.error('Error loading chainlist:', err);
    });
  }, []);
  const fetchLocalFile = useCallback(function (path) {
    return fetch('/public' + path).then(function (r) {
      if (!r.ok) throw new Error();
      return r.text();
    }).then(function (t) {
      if (t.trim().startsWith('<')) throw new Error();
      return t;
    }).catch(function () {
      return fetch(path).then(function (r) {
        if (!r.ok) throw new Error();
        return r.text();
      }).then(function (t) {
        if (t.trim().startsWith('<')) throw new Error();
        return t;
      });
    });
  }, []);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const localPath = version === 2 ? '/data/deploymentsV2.json' : '/data/deploymentsV1.json';
    const apiUrl = 'https://metadata.layerzero-api.com/v1/metadata/deployments';
    fetchLocalFile(localPath).then(function (text) {
      var data = JSON.parse(text);
      if (Array.isArray(data)) {
        setDeploymentsData(data);
        setIsLoading(false);
      } else {
        throw new Error('Unexpected local format');
      }
    }).catch(function () {
      fetch(apiUrl).then(function (r) {
        if (!r.ok) throw new Error('Failed to fetch');
        return r.json();
      }).then(function (data) {
        try {
          var deploymentsArray = [];
          if (data && typeof data === 'object') {
            Object.entries(data).forEach(function (entry) {
              var chainName = entry[0];
              var chainData = entry[1];
              var chainStatus = chainData && chainData.chainDetails && chainData.chainDetails.chainStatus || chainData && chainData.chainStatus;
              if (chainStatus === 'INACTIVE' || chainStatus === 'DEPRECATED') return;
              if (!chainData || !chainData.deployments || !Array.isArray(chainData.deployments)) return;
              chainData.deployments.forEach(function (deployment) {
                if (!deployment) return;
                var isV2 = deployment.version === 2 || !!deployment.endpointV2;
                var isV1 = deployment.version === 1 || !!deployment.endpoint;
                if (version === 2 && isV2 || version === 1 && isV1) {
                  var nameStr = chainName || '';
                  var displayName = chainData.chainDetails && chainData.chainDetails.name || nameStr.replace(/-/g, ' ').split(' ').map(function (w) {
                    return w.charAt(0).toUpperCase() + w.slice(1);
                  }).join(' ');
                  deploymentsArray.push({
                    chainKey: (deployment.chainKey || chainData.chainKey || chainName || '').toString(),
                    chainDisplayName: displayName,
                    nativeChainId: chainData.chainDetails && chainData.chainDetails.nativeChainId || deployment.nativeChainId || 'N/A',
                    stage: deployment.stage || (nameStr.includes('testnet') ? 'testnet' : 'mainnet'),
                    eid: (deployment.eid || '').toString(),
                    endpointV2: deployment.endpointV2,
                    endpoint: deployment.endpoint,
                    controller: deployment.controller,
                    sendUln302: deployment.sendUln302,
                    receiveUln302: deployment.receiveUln302,
                    readLib1002: deployment.readLib1002,
                    executor: deployment.executor,
                    executorProxy: deployment.executorProxy,
                    dvnProxy: deployment.dvnProxy,
                    deadDVN: deployment.deadDVN,
                    blockedMessageLib: deployment.blockedMessageLib,
                    version: deployment.version,
                    isNew: false,
                    note: notesMap[(deployment.eid || '').toString()] || null
                  });
                }
              });
            });
          }
          setDeploymentsData(deploymentsArray);
        } catch (err) {
          console.error('Error processing deployments:', err);
          setError('Error processing data');
        }
        setIsLoading(false);
      }).catch(function (err) {
        console.error('Error loading deployments:', err);
        setError('Error loading data');
        setIsLoading(false);
      });
    });
  }, [version, fetchLocalFile]);
  const getEndpointAddress = useCallback(deployment => {
    if (!deployment) return null;
    const chainKey = (deployment.chainKey || '').toString().toLowerCase();
    if (chainKey === 'ton') {
      return deployment.controller && deployment.controller.address;
    }
    if (version === 1) {
      return deployment.endpoint && deployment.endpoint.address;
    }
    return deployment.endpointV2 && deployment.endpointV2.address;
  }, [version]);
  const chains = useMemo(() => {
    if (!Array.isArray(deploymentsData)) return [];
    try {
      const filteredDeployments = selectedStage.length > 0 ? deploymentsData.filter(d => d && selectedStage.includes(d.stage)) : deploymentsData;
      const chainMap = {};
      filteredDeployments.forEach(d => {
        if (!d) return;
        const key = (d.chainKey || '').toString().toLowerCase();
        if (key && !chainMap[key]) {
          chainMap[key] = {
            value: key,
            label: (d.chainDisplayName || '').toString() || key
          };
        }
      });
      return Object.values(chainMap).sort((a, b) => (a.label || '').localeCompare(b.label || ''));
    } catch (err) {
      console.error('Error getting chains:', err);
      return [];
    }
  }, [deploymentsData, selectedStage]);
  const filteredData = useMemo(() => {
    if (!Array.isArray(deploymentsData)) return [];
    try {
      const searchLower = (searchTerm || '').toString().toLowerCase();
      let data = deploymentsData.filter(d => {
        if (!d) return false;
        const matchesStage = selectedStage.length === 0 || selectedStage.includes(d.stage);
        const dChainKey = (d.chainKey || '').toString().toLowerCase();
        const matchesChain = selectedChains.length === 0 || selectedChains.includes(dChainKey);
        const dDisplayName = (d.chainDisplayName || '').toString().toLowerCase();
        const matchesSearch = !searchLower || dDisplayName.includes(searchLower) || dChainKey.includes(searchLower);
        const hasEndpoint = !!getEndpointAddress(d);
        return matchesStage && matchesChain && matchesSearch && hasEndpoint;
      });
      if (showRecentlyAdded) {
        data = data.filter(d => d && d.isNew);
      }
      return data.sort((a, b) => {
        const aName = (a && a.chainDisplayName || '').toString();
        const bName = (b && b.chainDisplayName || '').toString();
        return aName.localeCompare(bName);
      });
    } catch (err) {
      console.error('Error filtering data:', err);
      return [];
    }
  }, [deploymentsData, selectedStage, selectedChains, searchTerm, showRecentlyAdded, getEndpointAddress]);
  const filteredChains = useMemo(() => {
    if (!Array.isArray(chains)) return [];
    if (!searchTerm) return chains;
    const searchLower = (searchTerm || '').toString().toLowerCase();
    return chains.filter(c => {
      if (!c) return false;
      const cLabel = (c.label || '').toString().toLowerCase();
      const cValue = (c.value || '').toString().toLowerCase();
      return cLabel.includes(searchLower) || cValue.includes(searchLower);
    });
  }, [chains, searchTerm]);
  const totalCount = useMemo(() => {
    if (!Array.isArray(deploymentsData)) return 0;
    return deploymentsData.filter(d => {
      if (!d) return false;
      return selectedStage.length === 0 ? d.stage === 'mainnet' : selectedStage.includes(d.stage);
    }).length;
  }, [deploymentsData, selectedStage]);
  useEffect(() => {
    const handleClickOutside = event => {
      if (searchContainerRef.current && !searchContainerRef.current.contains(event.target)) {
        setIsChainsListOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);
  const handleReset = () => {
    setSelectedChains([]);
    setSearchTerm('');
    setShowRecentlyAdded(false);
    setSelectedStage(['mainnet']);
    setIsChainsListOpen(false);
  };
  const getContracts = useCallback(deployment => {
    if (!deployment) return [];
    const contracts = [];
    try {
      const endpointAddr = getEndpointAddress(deployment);
      const chainKey = (deployment.chainKey || '').toString().toLowerCase();
      const isTon = chainKey === 'ton';
      const isSolana = chainKey === 'solana' || chainKey === 'solana-testnet';
      if (endpointAddr) {
        contracts.push({
          name: isTon ? 'Controller' : version === 2 ? 'EndpointV2' : 'EndpointV1',
          address: endpointAddr
        });
      }
      if (isTon) {
        if (deployment.executorProxy && deployment.executorProxy.address) {
          contracts.push({
            name: 'ExecutorProxy',
            address: deployment.executorProxy.address
          });
        }
        if (deployment.dvnProxy && deployment.dvnProxy.address) {
          contracts.push({
            name: 'DVN Proxy',
            address: deployment.dvnProxy.address
          });
        }
      } else if (isSolana) {
        if (deployment.sendUln302 && deployment.sendUln302.address) {
          contracts.push({
            name: 'ULN302',
            address: deployment.sendUln302.address
          });
        }
        if (deployment.executor && deployment.executor.address) {
          contracts.push({
            name: 'Executor',
            address: deployment.executor.address
          });
        }
      } else if (version === 2) {
        if (deployment.sendUln302 && deployment.sendUln302.address) {
          contracts.push({
            name: 'SendUln302',
            address: deployment.sendUln302.address
          });
        }
        if (deployment.receiveUln302 && deployment.receiveUln302.address) {
          contracts.push({
            name: 'ReceiveUln302',
            address: deployment.receiveUln302.address
          });
        }
        if (deployment.readLib1002 && deployment.readLib1002.address) {
          contracts.push({
            name: 'ReadLib1002',
            address: deployment.readLib1002.address
          });
        }
        if (deployment.executor && deployment.executor.address) {
          contracts.push({
            name: 'LZ Executor',
            address: deployment.executor.address
          });
        }
        if (deployment.deadDVN && deployment.deadDVN.address) {
          contracts.push({
            name: 'LZ Dead DVN',
            address: deployment.deadDVN.address
          });
        }
        if (deployment.blockedMessageLib && deployment.blockedMessageLib.address) {
          contracts.push({
            name: 'Blocked Message Library',
            address: deployment.blockedMessageLib.address
          });
        }
      }
    } catch (err) {
      console.error('Error getting contracts:', err);
    }
    return contracts;
  }, [getEndpointAddress, version]);
  const styles = {
    container: {
      fontFamily: 'inherit',
      width: '100%'
    },
    titleBar: {
      display: 'flex',
      flexWrap: 'wrap',
      alignItems: 'center',
      gap: '12px',
      marginBottom: '16px',
      padding: '12px 16px',
      background: isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.02)',
      borderRadius: '12px'
    },
    networkCount: {
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      fontWeight: 600,
      fontSize: '14px'
    },
    countBadge: {
      background: isDark ? 'rgba(124,58,237,0.2)' : 'rgba(124,58,237,0.1)',
      color: '#7c3aed',
      padding: '2px 8px',
      borderRadius: '12px',
      fontSize: '12px',
      fontWeight: 600
    },
    networkTypeSwitch: {
      display: 'flex',
      gap: '4px',
      background: isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)',
      padding: '4px',
      borderRadius: '8px'
    },
    switchButton: {
      padding: '6px 12px',
      border: 'none',
      borderRadius: '6px',
      cursor: 'pointer',
      fontSize: '13px',
      fontWeight: 500,
      transition: 'all 0.2s'
    },
    switchButtonActive: {
      background: '#7c3aed',
      color: '#fff'
    },
    switchButtonInactive: {
      background: 'transparent',
      color: isDark ? '#9ca3af' : '#6b7280'
    },
    checkbox: {
      display: 'flex',
      alignItems: 'center',
      gap: '6px',
      fontSize: '13px',
      cursor: 'pointer'
    },
    searchContainer: {
      position: 'relative',
      flex: 1,
      minWidth: '200px'
    },
    searchInput: {
      width: '100%',
      padding: '8px 12px',
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)'),
      borderRadius: '8px',
      background: isDark ? 'rgba(0,0,0,0.2)' : '#fff',
      color: isDark ? '#fff' : '#000',
      fontSize: '14px',
      outline: 'none'
    },
    chainsList: {
      position: 'absolute',
      top: '100%',
      left: 0,
      right: 0,
      maxHeight: '300px',
      overflowY: 'auto',
      background: isDark ? '#1f2937' : '#fff',
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)'),
      borderRadius: '8px',
      marginTop: '4px',
      zIndex: 100,
      boxShadow: '0 4px 12px rgba(0,0,0,0.15)'
    },
    chainItem: {
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      padding: '8px 12px',
      cursor: 'pointer',
      fontSize: '13px'
    },
    selectedChainBubble: {
      display: 'inline-flex',
      alignItems: 'center',
      gap: '6px',
      padding: '4px 8px',
      background: isDark ? 'rgba(124,58,237,0.2)' : 'rgba(124,58,237,0.1)',
      borderRadius: '16px',
      fontSize: '12px',
      marginRight: '6px',
      marginBottom: '6px'
    },
    removeButton: {
      background: 'none',
      border: 'none',
      cursor: 'pointer',
      fontSize: '14px',
      padding: '0 2px',
      opacity: 0.7,
      color: 'inherit'
    },
    button: {
      padding: '8px 16px',
      border: 'none',
      borderRadius: '8px',
      cursor: 'pointer',
      fontSize: '13px',
      fontWeight: 500,
      background: isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)',
      color: isDark ? '#fff' : '#000'
    },
    tableContainer: {
      overflowX: 'auto',
      borderRadius: '8px',
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)'),
      background: isDark ? 'rgba(0,0,0,0.2)' : '#fff',
      margin: 0,
      padding: 0,
      width: '100%',
      maxWidth: '100%'
    },
    table: {
      width: '100%',
      borderCollapse: 'collapse',
      fontSize: '14px'
    },
    th: {
      textAlign: 'left',
      padding: '10px 1.5rem',
      background: 'transparent',
      fontWeight: 400,
      fontSize: '12px',
      color: isDark ? '#9ca3af' : '#6b7280',
      borderBottom: '1px solid ' + (isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)')
    },
    td: {
      padding: '12px 1.5rem',
      borderBottom: '1px solid ' + (isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)'),
      verticalAlign: 'middle'
    },
    chainCell: {
      display: 'flex',
      alignItems: 'center',
      gap: '6px',
      paddingLeft: '2px'
    },
    chainInfo: {
      flex: 1,
      minWidth: 0
    },
    chainName: {
      fontWeight: 600,
      fontSize: '13px',
      marginBottom: '4px',
      color: isDark ? '#fff' : '#111',
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    },
    chainMeta: {
      fontSize: '11px',
      color: isDark ? '#6b7280' : '#9ca3af',
      marginBottom: '1px'
    },
    newBadge: {
      display: 'inline-block',
      padding: '2px 8px',
      background: 'linear-gradient(135deg, #10b981, #059669)',
      color: '#fff',
      borderRadius: '12px',
      fontSize: '10px',
      fontWeight: 600,
      marginTop: '4px'
    },
    chainNoteBox: {
      display: 'flex',
      alignItems: 'flex-start',
      gap: '12px',
      marginTop: '16px',
      padding: '16px 20px',
      background: isDark ? 'rgba(202, 138, 4, 0.2)' : '#fefce8',
      border: '1px solid ' + (isDark ? 'rgb(113, 63, 18)' : '#fde68a'),
      borderRadius: '16px',
      fontSize: '16px',
      lineHeight: '28px',
      color: isDark ? '#a4a2a6' : '#374151',
      overflow: 'hidden'
    },
    chainNoteIcon: {
      flexShrink: 0,
      marginTop: '2px',
      color: isDark ? '#fde047' : '#854d0e'
    },
    chainNoteText: {
      flex: 1
    },
    contractsContainer: {
      display: 'flex',
      flexDirection: 'column',
      gap: '4px'
    },
    contractItem: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: '4px 8px',
      background: isDark ? 'rgba(255,255,255,0.04)' : 'rgba(0,0,0,0.03)',
      borderRadius: '4px',
      fontSize: '11px',
      transition: 'all 0.15s',
      border: '1px solid transparent'
    },
    contractItemHover: {
      borderColor: '#7c3aed'
    },
    contractLeft: {
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      flex: 1,
      minWidth: 0
    },
    contractLink: {
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      textDecoration: 'none',
      color: 'inherit',
      flex: 1,
      minWidth: 0
    },
    contractName: {
      fontWeight: 500,
      fontSize: '11px',
      color: isDark ? '#fff' : '#111',
      whiteSpace: 'nowrap'
    },
    contractAddress: {
      fontFamily: 'monospace',
      fontSize: '11px',
      color: isDark ? '#6b7280' : '#9ca3af',
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    },
    copyButton: {
      background: 'none',
      border: 'none',
      cursor: 'pointer',
      padding: '4px',
      color: isDark ? '#6b7280' : '#9ca3af',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      borderRadius: '4px',
      transition: 'all 0.15s'
    },
    copyIcon: {
      width: 16,
      height: 16
    },
    loading: {
      textAlign: 'center',
      padding: '40px',
      opacity: 0.6
    },
    errorStyle: {
      textAlign: 'center',
      padding: '40px',
      color: '#ef4444'
    },
    noResults: {
      textAlign: 'center',
      padding: '40px',
      opacity: 0.6
    },
    networkIcon: {
      width: 22,
      height: 22,
      minWidth: 22,
      backgroundSize: 'contain',
      backgroundRepeat: 'no-repeat',
      backgroundPosition: 'center',
      borderRadius: '50%',
      flexShrink: 0
    },
    linksCell: {
      verticalAlign: 'middle',
      whiteSpace: 'nowrap'
    },
    linksContainer: {
      display: 'flex',
      alignItems: 'center',
      gap: '6px',
      justifyContent: 'center'
    },
    actionButton: {
      display: 'inline-flex',
      alignItems: 'center',
      justifyContent: 'center',
      width: '28px',
      height: '28px',
      borderRadius: '6px',
      background: isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.03)',
      border: 'none',
      cursor: 'pointer',
      transition: 'all 0.15s',
      color: isDark ? '#9ca3af' : '#6b7280'
    },
    actionButtonDisabled: {
      opacity: 0.3,
      cursor: 'not-allowed'
    },
    metamaskIcon: {
      width: '16px',
      height: '16px'
    },
    mobileHeader: {
      marginBottom: '20px'
    },
    mobileSearchInput: {
      width: '100%',
      padding: '12px 16px',
      marginBottom: '12px',
      borderRadius: '4px',
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : '#e5e7eb'),
      background: isDark ? 'rgba(255,255,255,0.05)' : '#fff',
      color: isDark ? '#fff' : '#000',
      fontSize: '16px',
      outline: 'none',
      boxSizing: 'border-box'
    },
    mobileTabs: {
      display: 'flex',
      gap: '12px',
      width: '100%'
    },
    mobileTab: {
      flex: 1,
      padding: '10px',
      borderRadius: '4px',
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.2)' : '#000'),
      background: 'transparent',
      cursor: 'pointer',
      textAlign: 'center',
      fontWeight: 600,
      fontSize: '14px',
      color: isDark ? '#fff' : '#000',
      transition: 'all 0.2s'
    },
    mobileTabActive: {
      background: isDark ? '#fff' : '#000',
      color: isDark ? '#000' : '#fff',
      border: '1px solid ' + (isDark ? '#fff' : '#000')
    },
    mobileCard: {
      border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : '#e5e7eb'),
      borderRadius: '8px',
      padding: '16px',
      marginBottom: '16px',
      background: isDark ? 'rgba(255,255,255,0.02)' : '#fff',
      boxShadow: '0 1px 3px rgba(0,0,0,0.05)',
      display: 'flex',
      flexDirection: 'column',
      gap: '8px'
    },
    mobileCardHeader: {
      display: 'flex',
      flexDirection: 'row',
      alignItems: 'center',
      gap: '8px',
      marginBottom: '12px',
      paddingBottom: '12px',
      borderBottom: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : '#f3f4f6')
    },
    mobileCardTitle: {
      fontSize: '18px',
      fontWeight: 700,
      color: isDark ? '#fff' : '#000',
      lineHeight: '1.2'
    },
    mobileCardRow: {
      fontSize: '14px',
      lineHeight: '1.6',
      display: 'flex',
      alignItems: 'baseline',
      gap: '6px'
    },
    mobileCardLabel: {
      fontWeight: 700,
      color: isDark ? '#fff' : '#000'
    },
    mobileCardValue: {
      color: isDark ? '#9ca3af' : '#4b5563',
      wordBreak: 'break-all'
    },
    mobileContractsList: {
      display: 'flex',
      flexDirection: 'column',
      gap: '0px'
    },
    mobileExplorerLink: {
      color: '#7c3aed',
      textDecoration: 'none',
      fontWeight: 500,
      transition: 'color 0.2s'
    },
    mobileRpcContainer: {
      marginTop: '12px',
      paddingTop: '8px',
      display: 'flex',
      alignItems: 'center',
      gap: '6px'
    },
    mobileRpcLabel: {
      fontWeight: 700,
      fontSize: '14px',
      color: isDark ? '#fff' : '#000'
    }
  };
  if (isLoading) {
    return <div style={styles.loading}>Loading deployments...</div>;
  }
  if (error) {
    return <div style={styles.errorStyle}>{error}</div>;
  }
  if (isMobile) {
    return <>
      <style>{`
        /* LayerZero Mobile Card Styles */
        .lz-mobile-card-header {
          display: flex !important;
          flex-direction: row !important;
          align-items: center !important;
          gap: 12px !important;
          margin-bottom: 12px;
          padding-bottom: 12px;
          border-bottom: 1px solid ${isDark ? 'rgba(255,255,255,0.1)' : '#e5e7eb'};
        }
        .lz-mobile-icon-wrapper {
          display: inline-flex !important;
          align-items: center !important;
          justify-content: center !important;
          flex-shrink: 0 !important;
          width: 24px !important;
          height: 24px !important;
          position: relative !important;
        }
        /* Hide Mintlify zoom ghost element */
        .lz-mobile-icon-wrapper [data-rmiz-ghost] {
          display: none !important;
          visibility: hidden !important;
          position: absolute !important;
          width: 0 !important;
          height: 0 !important;
        }
        .lz-mobile-icon-wrapper [data-rmiz],
        .lz-mobile-icon-wrapper [data-rmiz-content] {
          display: inline-flex !important;
          align-items: center !important;
          width: 24px !important;
          height: 24px !important;
          line-height: 0 !important;
          margin: 0 !important;
          padding: 0 !important;
        }
        .lz-mobile-icon-wrapper img {
          width: 24px !important;
          height: 24px !important;
          display: block !important;
        }
        .lz-mobile-card-title {
          font-size: 18px !important;
          font-weight: 700 !important;
          margin: 0 !important;
          line-height: 1.2 !important;
          color: ${isDark ? '#fff' : '#000'} !important;
        }
      `}</style>
      <div style={styles.container}>
        <div style={styles.mobileHeader}>
          <input type="text" placeholder="Search for chains..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} style={styles.mobileSearchInput} />
          <div style={styles.mobileTabs}>
            {['Mainnet', 'Testnet'].map(stage => {
      const stageLower = stage.toLowerCase();
      const isActive = selectedStage.includes(stageLower);
      return <button key={stage} onClick={() => setSelectedStage([stageLower])} style={Object.assign({}, styles.mobileTab, isActive ? styles.mobileTabActive : {})}>
                  {stage}
                </button>;
    })}
          </div>
        </div>

        <div>
          {filteredData.map((deployment, idx) => {
      if (!deployment) return null;
      const contracts = getContracts(deployment);
      const chainKey = (deployment.chainKey || '').toString().toLowerCase();
      return <div key={idx} style={styles.mobileCard}>
                 <div className="lz-mobile-card-header">
                   <div className="lz-mobile-icon-wrapper">
                     {renderNetworkIcon(chainKey, deployment.chainDisplayName, 24)}
                   </div>
                   <div className="lz-mobile-card-title">
                     {(deployment.chainDisplayName || '').toString()}
                   </div>
                 </div>

                 <div style={styles.mobileCardRow}>
                   <span style={styles.mobileCardLabel}>Chain Id:</span>
                   <span style={styles.mobileCardValue}>{deployment.nativeChainId}</span>
                 </div>

                 {getEndpointAddress(deployment) && <div style={styles.mobileCardRow}>
                     <span style={styles.mobileCardLabel}>Endpoint:</span>
                     <span style={styles.mobileCardValue}>
                        <a href={`${getExplorerUrl(deployment)}/${getEndpointAddress(deployment)}`} target="_blank" rel="noreferrer" style={styles.mobileExplorerLink}>
                           {getEndpointAddress(deployment).slice(0, 7) + '...'}
                        </a>
                     </span>
                   </div>}

                 {deployment.eid && <div style={styles.mobileCardRow}>
                      <span style={styles.mobileCardLabel}>Endpoint Id:</span>
                      <span style={styles.mobileCardValue}>{deployment.eid}</span>
                    </div>}

                 <div style={styles.mobileContractsList}>
                   {contracts.map((c, i) => {
        if (!c || !c.address) return null;
        return <div key={i} style={styles.mobileCardRow}>
                           <span style={styles.mobileCardLabel}>{c.name}:</span>
                           <span style={styles.mobileCardValue}>
                              <a href={`${getExplorerUrl(deployment)}/${c.address}`} target="_blank" rel="noreferrer" style={styles.mobileExplorerLink}>
                                {c.address.slice(0, 7) + '...'}
                              </a>
                           </span>
                        </div>;
      })}
                 </div>

                 <div style={styles.mobileRpcContainer}>
                    <span style={styles.mobileRpcLabel}>RPC:</span>
                    {isEvmChain(chainKey) && <button onClick={() => addToMetaMask(deployment)} style={{
        background: 'none',
        border: 'none',
        padding: 0,
        cursor: 'pointer',
        display: 'flex',
        alignItems: 'center'
      }}>
                           <svg style={{
        width: 24,
        height: 24
      }} viewBox="0 0 35 33" fill="none">
                              <path d="M32.96 1L19.53 11.02l2.48-5.88L32.96 1z" fill="#E17726" stroke="#E17726" strokeWidth="0.25" />
                              <path d="M2.04 1l13.3 10.12-2.35-5.98L2.04 1zM28.23 23.53l-3.57 5.47 7.64 2.1 2.2-7.44-6.27-.13zM.52 23.66l2.18 7.44 7.63-2.1-3.56-5.47-6.25.13z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" />
                              <path d="M9.96 14.47l-2.13 3.22 7.59.34-.25-8.17-5.21 4.61zM25.04 14.47l-5.28-4.7-.17 8.25 7.58-.34-2.13-3.21zM10.33 29l4.58-2.23-3.95-3.09-.63 5.32zM20.09 26.77l4.58 2.23-.64-5.32-3.94 3.09z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" />
                              <path d="M24.67 29l-4.58-2.23.37 2.97-.04 1.26 4.25-2zM10.33 29l4.25 2-.03-1.26.36-2.97-4.58 2.23z" fill="#D5BFB2" stroke="#D5BFB2" strokeWidth="0.25" />
                              <path d="M14.66 21.92l-3.8-1.12 2.69-1.23 1.11 2.35zM20.34 21.92l1.11-2.35 2.7 1.23-3.81 1.12z" fill="#233447" stroke="#233447" strokeWidth="0.25" />
                              <path d="M10.33 29l.66-5.47-4.22.12 3.56 5.35zM24.01 23.53l.66 5.47 3.56-5.35-4.22-.12zM27.17 17.69l-7.58.34.7 3.89 1.11-2.35 2.7 1.23 3.07-3.11zM10.86 20.8l2.69-1.23 1.11 2.35.71-3.89-7.59-.34 3.08 3.11z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" />
                              <path d="M7.78 17.69l3.19 6.22-.11-3.11-3.08-3.11zM24.1 20.8l-.12 3.11 3.19-6.22-3.07 3.11zM15.37 18.03l-.71 3.89.89 4.6.2-6.06-.38-2.43zM19.59 18.03l-.37 2.42.18 6.07.9-4.6-.71-3.89z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" />
                              <path d="M20.3 21.92l-.9 4.6.65.45 3.94-3.09.12-3.11-3.81 1.15zM10.86 20.8l.11 3.08 3.95 3.09.64-.45-.89-4.6-3.81-1.12z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" />
                              <path d="M20.38 31l.04-1.26-.34-.3h-5.16l-.33.3.03 1.26-4.25-2 1.49 1.22 3.01 2.09h5.26l3.02-2.09 1.48-1.22-4.25 2z" fill="#C0AC9D" stroke="#C0AC9D" strokeWidth="0.25" />
                              <path d="M20.09 26.77l-.65-.45h-3.88l-.64.45-.37 2.97.34-.3h5.16l.34.3-.3-2.97z" fill="#161616" stroke="#161616" strokeWidth="0.25" />
                              <path d="M33.52 11.53l1.14-5.5L32.96 1l-12.87 9.55 4.95 4.19 6.99 2.04 1.54-1.8-.67-.49 1.07-.97-.82-.64 1.07-.81-.7-.54zM.34 6.03l1.15 5.5-.74.54 1.07.81-.81.64 1.07.97-.68.49 1.54 1.8 6.99-2.04 4.95-4.19L2.01 1 .34 6.03z" fill="#763E1A" stroke="#763E1A" strokeWidth="0.25" />
                              <path d="M32.03 16.78l-6.99-2.04 2.13 3.22-3.19 6.22 4.2-.05h6.27l-2.42-7.35zM9.96 14.74l-6.99 2.04-2.41 7.35h6.25l4.2.05-3.19-6.22 2.14-3.22zM19.59 18.03l.45-7.75 2.03-5.5H12.93l2.01 5.5.47 7.75.17 2.44.01 6.05h3.88l.02-6.05.1-2.44z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" />
                           </svg>
                        </button>}
                 </div>
               </div>;
    })}
        </div>
      </div>
      </>;
  }
  return <div className="lz-deployments-root" style={styles.container}>
      <style>{`
        .lz-deployments-root [data-table-wrapper] {
          width: 100% !important;
          max-width: 100% !important;
          margin: 0 !important;
          padding: 0 !important;
          contain: none !important;
          overflow: visible !important;
        }
        .lz-deployments-root [data-table-wrapper] > div {
          padding: 0 !important;
          max-width: 100% !important;
        }
        .lz-contract-item:hover {
          border-color: #7c3aed !important;
        }
        .lz-contract-item a,
        .lz-contract-item a.link,
        .lz-contract-item a:hover,
        .lz-contract-item a.link:hover {
          text-decoration: none !important;
          border-bottom: none !important;
          box-shadow: none !important;
        }
        .lz-contract-item a span {
          text-decoration: none !important;
          border-bottom: none !important;
        }
        .lz-tooltip {
          position: relative;
        }
        .lz-tooltip::after {
          content: attr(data-tooltip);
          position: absolute;
          bottom: calc(100% + 6px);
          left: 50%;
          transform: translateX(-50%);
          padding: 4px 8px;
          border-radius: 4px;
          font-size: 11px;
          font-weight: 500;
          white-space: nowrap;
          pointer-events: none;
          opacity: 0;
          transition: opacity 0.15s ease-out;
          background: ${isDark ? '#e5e7eb' : '#1f2937'};
          color: ${isDark ? '#1f2937' : '#f9fafb'};
        }
        .lz-tooltip:hover::after {
          opacity: 1;
        }
        /* Fix icon alignment with Mintlify zoom wrapper */
        #lz-deployments-table td.lz-col-chain [data-rmiz],
        #lz-deployments-table td.lz-col-chain [data-rmiz-content],
        .lz-chains-dropdown [data-rmiz],
        .lz-chains-dropdown [data-rmiz-content],
        .lz-selected-chains [data-rmiz],
        .lz-selected-chains [data-rmiz-content] {
          display: inline-flex !important;
          align-items: center !important;
          height: 18px !important;
          width: 18px !important;
          max-height: 18px !important;
          line-height: 0 !important;
          font-size: 0 !important;
          overflow: hidden !important;
          flex-shrink: 0 !important;
        }
        #lz-deployments-table td.lz-col-chain [data-rmiz],
        #lz-deployments-table td.lz-col-chain [data-rmiz-content] {
          height: 24px !important;
          width: 24px !important;
          max-height: 24px !important;
        }
        .lz-selected-chains [data-rmiz],
        .lz-selected-chains [data-rmiz-content] {
          height: 14px !important;
          width: 14px !important;
          max-height: 14px !important;
        }
        #lz-deployments-table td.lz-col-chain [data-rmiz-ghost],
        .lz-chains-dropdown [data-rmiz-ghost],
        .lz-selected-chains [data-rmiz-ghost] {
          display: none !important;
          position: absolute !important;
          visibility: hidden !important;
          width: 0 !important;
          height: 0 !important;
        }
        #lz-deployments-table {
          width: 100% !important;
        }
        #lz-deployments-table th.lz-col-chain,
        #lz-deployments-table td.lz-col-chain {
          width: 35% !important;
          min-width: 180px !important;
          padding-left: 3rem !important;
        }
        #lz-deployments-table th.lz-col-contracts,
        #lz-deployments-table td.lz-col-contracts {
          min-width: 200px !important;
        }
        #lz-deployments-table th.lz-col-links,
        #lz-deployments-table td.lz-col-links {
          padding-right: 3rem !important;
        }
      `}</style>
      <div style={styles.titleBar}>
        <div style={styles.networkCount}>
          <span>Connected Networks</span>
          <span style={styles.countBadge}>{totalCount}</span>
        </div>

        <div style={styles.networkTypeSwitch}>
          {['All', 'Mainnet', 'Testnet'].map(function (label) {
    var value = label.toLowerCase();
    var isActive = value === 'all' && selectedStage.length === 0 || value !== 'all' && selectedStage.includes(value);
    return <button key={'switch-' + label} onClick={function () {
      setSelectedStage(value === 'all' ? [] : [value]);
    }} style={Object.assign({}, styles.switchButton, isActive ? styles.switchButtonActive : styles.switchButtonInactive)}>
                {label}
              </button>;
  })}
        </div>

        <label style={styles.checkbox}>
          <input type="checkbox" checked={showRecentlyAdded} onChange={function (e) {
    setShowRecentlyAdded(e.target.checked);
  }} />
          Recently Added
        </label>
      </div>

      <div style={styles.titleBar}>
        <div style={styles.searchContainer} ref={searchContainerRef}>
          <input type="text" placeholder="Search for chains..." value={searchTerm} onChange={function (e) {
    setSearchTerm(e.target.value);
    setIsChainsListOpen(true);
  }} onFocus={function () {
    setIsChainsListOpen(true);
  }} style={styles.searchInput} />
          {isChainsListOpen && filteredChains.length > 0 && <div className="lz-chains-dropdown" style={styles.chainsList}>
              {filteredChains.map(function (chain, idx) {
    if (!chain || !chain.value) return null;
    var isSelected = selectedChains.includes(chain.value);
    return <div key={'chain-' + chain.value + '-' + idx} style={Object.assign({}, styles.chainItem, {
      background: isSelected ? isDark ? 'rgba(124,58,237,0.2)' : 'rgba(124,58,237,0.1)' : 'transparent'
    })} onClick={function () {
      var newSelected = isSelected ? selectedChains.filter(function (c) {
        return c !== chain.value;
      }) : selectedChains.concat([chain.value]).slice(0, 10);
      setSelectedChains(newSelected);
    }}>
                    {renderNetworkIcon(chain.value, chain.label, 18)}
                    <span>{chain.label}</span>
                  </div>;
  })}
            </div>}
        </div>

        <button style={styles.button} onClick={function () {
    window.open('https://metadata.layerzero-api.com/v1/metadata/deployments', '_blank');
  }}>
          View Metadata
        </button>
        <button style={styles.button} onClick={handleReset}>Reset</button>
      </div>

      {selectedChains.length > 0 && <div className="lz-selected-chains" style={{
    display: 'flex',
    flexWrap: 'wrap',
    alignItems: 'center',
    padding: '0 16px 12px'
  }}>
          {selectedChains.map(function (chain, idx) {
    var chainInfo = chains.find(function (c) {
      return c && c.value === chain;
    });
    var chainLabel = chainInfo ? chainInfo.label : chain;
    return <span key={'selected-' + chain + '-' + idx} style={styles.selectedChainBubble}>
                {renderNetworkIcon(chain, chainLabel, 14)}
                {chainLabel}
                <button style={styles.removeButton} onClick={function () {
      setSelectedChains(selectedChains.filter(function (c) {
        return c !== chain;
      }));
    }}>x</button>
              </span>;
  })}
        </div>}

      <div style={styles.tableContainer}>
        <table id="lz-deployments-table" className="lz-table" style={styles.table}>
          <thead>
            <tr>
              <th className="lz-col-chain" style={styles.th}>Chain</th>
              <th className="lz-col-contracts" style={styles.th}>Contracts</th>
              <th className="lz-col-links" style={Object.assign({}, styles.th, {
    textAlign: 'center'
  })}>Actions</th>
            </tr>
          </thead>
          <tbody>
            {filteredData.map(function (deployment, index) {
    if (!deployment) return null;
    var contracts = getContracts(deployment);
    var chainKey = (deployment.chainKey || '').toString().toLowerCase();
    var displayName = (deployment.chainDisplayName || '').toString();
    var chainId = (deployment.nativeChainId || '').toString();
    var eid = (deployment.eid || '').toString();
    return <tr key={'row-' + eid + '-' + chainKey + '-' + index}>
                  <td className="lz-col-chain" style={styles.td}>
                    <div style={styles.chainCell}>
                      {renderNetworkIcon(chainKey, displayName, 24)}
                      <div style={styles.chainInfo}>
                        <div style={styles.chainName}>{displayName}</div>
                        <div style={styles.chainMeta}>Chain ID: {chainId}</div>
                        <div style={styles.chainMeta}>Endpoint ID: {eid}</div>
                        {deployment.isNew && <span style={styles.newBadge}>Recently Added</span>}
                      </div>
                    </div>
                  </td>
                  <td className="lz-col-contracts" style={styles.td}>
                    <div style={styles.contractsContainer}>
                      {contracts.map(function (c, i) {
      if (!c || !c.address) return null;
      var addr = (c.address || '').toString();
      var addrShort = addr.length > 20 ? addr.slice(0, 18) + '...' : addr;
      return <div key={'contract-' + addr + '-' + i} className="lz-contract-item" style={styles.contractItem}>
                            <a href={getExplorerUrl(deployment) + '/' + addr} target="_blank" rel="noreferrer" style={styles.contractLink}>
                              <span style={styles.contractName}>{(c.name || '').toString()}</span>
                              <span style={styles.contractAddress}>{addrShort}</span>
                            </a>
                            <button onClick={function (e) {
        handleCopy(addr, index + '-' + i, e);
      }} style={styles.copyButton} title={copiedAddress === index + '-' + i ? 'Copied!' : 'Copy address'}>
                              {copiedAddress === index + '-' + i ? <svg style={styles.copyIcon} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                                  <polyline points="20 6 9 17 4 12"></polyline>
                                </svg> : <svg style={styles.copyIcon} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                                  <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                                  <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                                </svg>}
                            </button>
                          </div>;
    })}
                    </div>
                  </td>
                  <td className="lz-col-links" style={Object.assign({}, styles.td, styles.linksCell)}>
                    <div style={styles.linksContainer}>
                      {version === 2 && (isEvmChain(chainKey) ? <a href={getQuickstartUrl(deployment)} className="lz-tooltip" data-tooltip="Quickstart" style={styles.actionButton}>
                            <svg style={{
      width: 14,
      height: 14
    }} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
                              <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
                            </svg>
                          </a> : <span className="lz-tooltip" data-tooltip="Quickstart" style={Object.assign({}, styles.actionButton, styles.actionButtonDisabled)}>
                            <svg style={{
      width: 14,
      height: 14
    }} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
                              <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
                            </svg>
                          </span>)}
                      {isEvmChain(chainKey) ? <button onClick={function () {
      addToMetaMask(deployment);
    }} className="lz-tooltip" data-tooltip="Add to wallet" style={styles.actionButton}>
                          <svg style={styles.metamaskIcon} viewBox="0 0 35 33" fill="none">
                            <path d="M32.96 1L19.53 11.02l2.48-5.88L32.96 1z" fill="#E17726" stroke="#E17726" strokeWidth="0.25" />
                            <path d="M2.04 1l13.3 10.12-2.35-5.98L2.04 1zM28.23 23.53l-3.57 5.47 7.64 2.1 2.2-7.44-6.27-.13zM.52 23.66l2.18 7.44 7.63-2.1-3.56-5.47-6.25.13z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" />
                            <path d="M9.96 14.47l-2.13 3.22 7.59.34-.25-8.17-5.21 4.61zM25.04 14.47l-5.28-4.7-.17 8.25 7.58-.34-2.13-3.21zM10.33 29l4.58-2.23-3.95-3.09-.63 5.32zM20.09 26.77l4.58 2.23-.64-5.32-3.94 3.09z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" />
                            <path d="M24.67 29l-4.58-2.23.37 2.97-.04 1.26 4.25-2zM10.33 29l4.25 2-.03-1.26.36-2.97-4.58 2.23z" fill="#D5BFB2" stroke="#D5BFB2" strokeWidth="0.25" />
                            <path d="M14.66 21.92l-3.8-1.12 2.69-1.23 1.11 2.35zM20.34 21.92l1.11-2.35 2.7 1.23-3.81 1.12z" fill="#233447" stroke="#233447" strokeWidth="0.25" />
                            <path d="M10.33 29l.66-5.47-4.22.12 3.56 5.35zM24.01 23.53l.66 5.47 3.56-5.35-4.22-.12zM27.17 17.69l-7.58.34.7 3.89 1.11-2.35 2.7 1.23 3.07-3.11zM10.86 20.8l2.69-1.23 1.11 2.35.71-3.89-7.59-.34 3.08 3.11z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" />
                            <path d="M7.78 17.69l3.19 6.22-.11-3.11-3.08-3.11zM24.1 20.8l-.12 3.11 3.19-6.22-3.07 3.11zM15.37 18.03l-.71 3.89.89 4.6.2-6.06-.38-2.43zM19.59 18.03l-.37 2.42.18 6.07.9-4.6-.71-3.89z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" />
                            <path d="M20.3 21.92l-.9 4.6.65.45 3.94-3.09.12-3.11-3.81 1.15zM10.86 20.8l.11 3.08 3.95 3.09.64-.45-.89-4.6-3.81-1.12z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" />
                            <path d="M20.38 31l.04-1.26-.34-.3h-5.16l-.33.3.03 1.26-4.25-2 1.49 1.22 3.01 2.09h5.26l3.02-2.09 1.48-1.22-4.25 2z" fill="#C0AC9D" stroke="#C0AC9D" strokeWidth="0.25" />
                            <path d="M20.09 26.77l-.65-.45h-3.88l-.64.45-.37 2.97.34-.3h5.16l.34.3-.3-2.97z" fill="#161616" stroke="#161616" strokeWidth="0.25" />
                            <path d="M33.52 11.53l1.14-5.5L32.96 1l-12.87 9.55 4.95 4.19 6.99 2.04 1.54-1.8-.67-.49 1.07-.97-.82-.64 1.07-.81-.7-.54zM.34 6.03l1.15 5.5-.74.54 1.07.81-.81.64 1.07.97-.68.49 1.54 1.8 6.99-2.04 4.95-4.19L2.01 1 .34 6.03z" fill="#763E1A" stroke="#763E1A" strokeWidth="0.25" />
                            <path d="M32.03 16.78l-6.99-2.04 2.13 3.22-3.19 6.22 4.2-.05h6.27l-2.42-7.35zM9.96 14.74l-6.99 2.04-2.41 7.35h6.25l4.2.05-3.19-6.22 2.14-3.22zM19.59 18.03l.45-7.75 2.03-5.5H12.93l2.01 5.5.47 7.75.17 2.44.01 6.05h3.88l.02-6.05.1-2.44z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" />
                          </svg>
                        </button> : <span className="lz-tooltip" data-tooltip="Add to wallet" style={Object.assign({}, styles.actionButton, styles.actionButtonDisabled)}>
                          <svg style={styles.metamaskIcon} viewBox="0 0 35 33" fill="none" opacity="0.3">
                            <path d="M32.96 1L19.53 11.02l2.48-5.88L32.96 1z" fill="#E17726" stroke="#E17726" strokeWidth="0.25" />
                            <path d="M2.04 1l13.3 10.12-2.35-5.98L2.04 1zM28.23 23.53l-3.57 5.47 7.64 2.1 2.2-7.44-6.27-.13zM.52 23.66l2.18 7.44 7.63-2.1-3.56-5.47-6.25.13z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" />
                          </svg>
                        </span>}
                    </div>
                  </td>
                </tr>;
  })}
          </tbody>
        </table>
      </div>

      {filteredData.length === 0 && !isLoading && <div style={styles.noResults}>
          <p>No chains match your filters.</p>
          <button style={styles.button} onClick={handleReset}>Reset filters</button>
        </div>}

      {(() => {
    if (filteredData.length !== 1) return null;
    var singleChain = filteredData[0];
    if (!singleChain || !singleChain.note) return null;
    return <div style={styles.chainNoteBox}>
            <div style={styles.chainNoteIcon}>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
              </svg>
            </div>
            <div style={styles.chainNoteText}>{singleChain.note}</div>
          </div>;
  })()}
    </div>;
};

Below you can find a description of the main LayerZero V2 contracts and find the corresponding deployment information for each blockchain network LayerZero supports.

<ContractAddressesTable version={2} />

<Info>
  **Endpoint Id** (`eid`) values have no relation to **Chain Id** (`chainId`) values. Since LayerZero spans both EVM and non-EVM chains, each Endpoint contract has a unique identifier known as the `eid` for determining which chain's `endpoint` to send to or receive messages from.

  When using LayerZero contract methods, be sure to use the correct `eid` listed below:

  * `30xxx`: refer to mainnet chains

  * `40xxx`: refer to testnet chains

  To see if a specific LayerZero contract supports another, use the `isSupportedEid()` method.
</Info>

## Contract Description

| **Contract Name**           | **Description**                                                                                                                                                                                                                                                                                           |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EndpointV2**              | The primary entrypoint into LayerZero V2 responsible for managing crosschain communications. It orchestrates message sending, receiving, and configuration management between various smart contract connections using message library contracts and internal mappings to track `OApp` specific settings. |
| **SendUln302**              | A message library for sending crosschain messages. It combines functionalities from `SendUlnBase` and `SendLibBaseE2` to ensure secure message dispatch.                                                                                                                                                  |
| **ReceiveUln302**           | A message library for receiving and verifying crosschain messages. It integrates `ReceiveUlnBase` and `ReceiveLibBaseE2` to maintain message integrity.                                                                                                                                                   |
| **SendUln301**              | A version of the send message library compatible with `EndpointV1` for backwards compatibility with `EndpointV2`.                                                                                                                                                                                         |
| **ReceiveUln301**           | A version of the receive message library compatible with `EndpointV1` for backwards compatibility with `EndpointV2`.                                                                                                                                                                                      |
| **LZ Executor**             | A contract responsible for executing received crosschain messages automatically with a specified `gas limit` and `msg.value` for a fee.                                                                                                                                                                   |
| **LZ Dead DVN**             | Represents a **[Dead Decentralized Verifier Network (DVN)](../concepts/glossary#dead-dvn)**. These contracts are placeholders used when the default LayerZero config is inactive and will require the OApp owner to manually configure the contract's config to use the pathway.                          |
| **Blocked Message Library** | A message library that blocks messages from being sent or received. Used to disable specific pathways at the protocol level.                                                                                                                                                                              |

## Checking Default Configs

To see the default configuration for a given pathway (i.e., from `Chain A` to `Chain B`), you can use [LayerZero Scan's Default Checker](https://layerzeroscan.com/tools/defaults?version=V2).

<img src="https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=5f2c64f8eacbff0796557ffb68056b57" alt="LayerZero Scan Default Configurations interface showing a table of pathway configurations from Ethereum to various destinations, displaying columns for Send Library (SendUln302), Receive Library (ReceiveUln302), DVN providers (LayerZero Labs, Google), Executor, and confirmation requirements" data-og-width="2746" width="2746" data-og-height="1008" height="1008" data-path="images/defaultchecker.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=280&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=414cbe19e8b11328e1996f1820d26952 280w, https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=560&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=564ce641d7039603c50d402459d2ddef 560w, https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=840&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=759ca1ceba1ceeb5c89dd4e50ac2ec44 840w, https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=1100&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=ea80177da9ffcd6510e99df5fddd0f8c 1100w, https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=1650&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=148baa2a9801bad3291d72e2795733cc 1650w, https://mintcdn.com/layerzero/qVdya_xVZRutFzkr/images/defaultchecker.png?w=2500&fit=max&auto=format&n=qVdya_xVZRutFzkr&q=85&s=ff211fb87c743511c6d1990a2971cb8f 2500w" />
