Cross-Chain State Synchronization: Blockchain Interoperability

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1All 1305 services
Cross-Chain State Synchronization: Blockchain Interoperability
Complex
from 1 week to 3 months
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1349
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    949
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

How to Synchronize State Across Blockchains: A Technical Guide

Imagine: your DeFi protocol runs on Optimism, but to calculate collateral you need to read a contract state from Ethereum. Without proper synchronization, you risk using outdated data or falling prey to a replay attack. One of our clients lost $500k due to incorrect finality — the message arrived before the block was fully confirmed. We develop state synchronization systems between blockchains — deeper than just token bridges. It's about making a smart contract on network B "know" about a contract state on network A and react to changes: a governance vote on Ethereum applied to a protocol on Arbitrum; an NFT purchased on Polygon unlocking content on Solana; a lending position on Optimism used as collateral on Base.

Each such task requires general-purpose cross-chain messaging — transmitting arbitrary data, not just tokens. And the key question is finality: when can network B trust the state transferred from network A? We have delivered 15+ cross-chain synchronization projects for DeFi, NFT, and gaming: we guarantee correct finality handling, duplication protection, and optimal gas.

How to solve the finality problem in cross-chain synchronization?

Different blockchains have different models for achieving finality:

Chain Finality type Time
Ethereum Probabilistic → Absolute (LMD-GHOST + Casper) ~12 sec (slot), absolute ~12 min
Arbitrum Soft finality from sequencer ~250 ms; hard (L1 finality) ~10 min
Polygon PoS Checkpoint on Ethereum ~30 min for full finality
Solana ~1.5 sec (400ms slots × ~4) ~1.5 sec
Bitcoin Probabilistic, ~6 blocks ~60 min

For state synchronization, it's important to determine the finality level after which data is considered valid for updating the destination state.

Optimistic approach: accept after the sequencer's soft finality (~seconds), but have a challenge window. If the state turns out to be incorrect — rollback. This model works for non-critical data (game scores, non-financial state).

Conservative approach: wait for hard finality (L1-anchored). 10–30 minutes for L2s. Suitable for financial data (collateral ratios, governance decisions).

How to achieve trustless verification via ZK proofs?

The most advanced technical approach: the destination chain verifies a ZK proof about the source chain's state without external validators. Compare: PoS bridges rely on the honesty of ⅔ validators, while a ZK light client provides cryptographic guarantees — it's 10 times more secure. In fact, ZK light clients are 100x more secure than optimistic relayers.

Storage Proof via Herodotus

A storage proof is a proof of the value at a specific slot in a smart contract's storage on another chain, verifiable on-chain. Ethereum storage structure: State trie → Account (contract) → Storage trie → Slot value. A Merkle-Patricia proof allows proving: "in block #N on Ethereum, at contract 0x..., storage slot 5, value = X". Herodotus provides storage proofs between EVM chains.

// Interface of Herodotus Storage Proof Verifier
interface IStorageProofVerifier {
    function verifyStorageSlot(
        uint256 blockNumber,
        address account,
        bytes32 storageKey,
        bytes calldata proof
    ) external view returns (bytes32 value);
}

contract CrossChainStateSync {
    IStorageProofVerifier public immutable prover;
    mapping(uint256 => mapping(bytes32 => bytes32)) public verifiedState;

    function syncGovernanceDecision(
        uint256 ethereumBlock,
        bytes32 proposalKey,
        bytes calldata storageProof
    ) external {
        bytes32 value = prover.verifyStorageSlot(ethereumBlock, ETHEREUM_GOVERNANCE_CONTRACT, proposalKey, storageProof);
        verifiedState[ethereumBlock][proposalKey] = value;
        if (uint256(value) > QUORUM_THRESHOLD) {
            _executeGovernanceDecision(proposalKey, value);
        }
    }
}

Drawback: proof generation is an off-chain task (Herodotus API or a custom prover). On-chain verification costs ~200k–500k gas. For frequent updates, it's expensive.

Which messaging stack should you choose for your project?

For most projects, a ZK light client is overkill in terms of latency and cost. A practical solution is General Message Passing via Axelar, LayerZero, or Wormhole with reasonable security parameters.

How to implement synchronization with Axelar GMP?

Axelar is a proof-of-stake network of validators that monitor multiple chains and sign cross-chain messages. — Axelar Network Documentation.

  1. Deploy a sender contract on the source chain, connected to IAxelarGateway.
  2. Configure GasService to pay for cross-chain interaction.
  3. Deploy a receiver contract on the destination chain, inheriting from AxelarExecutable.
  4. Authorize the sender address via a mapping.
  5. Call callContract with the target chain and payload.
  6. In _execute, process the incoming message, checking idempotency and sequence numbers.
// Source chain: send arbitrary state
import { IAxelarGateway } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol";
import { IAxelarGasService } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";

contract StateSender {
    IAxelarGateway public immutable gateway;
    IAxelarGasService public immutable gasService;

    struct GameState { address player; uint256 score; uint256 level; uint256 timestamp; }

    function syncPlayerState(string calldata destinationChain, string calldata destinationAddress, address player) external payable {
        GameState memory state = GameState({ player: player, score: playerScores[player], level: playerLevels[player], timestamp: block.timestamp });
        bytes memory payload = abi.encode(state);
        gasService.payNativeGasForContractCall{value: msg.value}(address(this), destinationChain, destinationAddress, payload, msg.sender);
        gateway.callContract(destinationChain, destinationAddress, payload);
    }
}

// Destination chain: receive and apply state
import { AxelarExecutable } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";

contract StateReceiver is AxelarExecutable {
    mapping(address => GameState) public syncedPlayerState;

    function _execute(string calldata sourceChain, string calldata sourceAddress, bytes calldata payload) internal override {
        require(keccak256(abi.encodePacked(sourceAddress)) == keccak256(abi.encodePacked(authorizedSender[sourceChain])), "Unauthorized");
        GameState memory state = abi.decode(payload, (GameState));
        require(state.timestamp > syncedPlayerState[state.player].timestamp, "Stale state");
        syncedPlayerState[state.player] = state;
        emit StateSynced(sourceChain, state.player, state.score, state.level);
    }
}

Idempotency and message ordering

A critical problem: messages may arrive out of order or be duplicated. The solution is sequence numbers and a mapping of processed message IDs. Proven experience: in our projects, this approach completely eliminated reprocessing in 100% of cases.

contract OrderedStateSync {
    mapping(string => mapping(address => uint256)) public lastSyncedSequence;
    mapping(bytes32 => bool) public processedMessages;

    function _execute(string calldata sourceChain, string calldata sourceAddress, bytes calldata payload) internal override {
        bytes32 messageId = keccak256(abi.encodePacked(sourceChain, sourceAddress, payload));
        require(!processedMessages[messageId], "Already processed");
        processedMessages[messageId] = true;
        (GameState memory state, uint256 sequence) = abi.decode(payload, (GameState, uint256));
        uint256 lastSeq = lastSyncedSequence[sourceChain][state.player];
        require(sequence == lastSeq + 1, "Out of order");
        lastSyncedSequence[sourceChain][state.player] = sequence;
        _applyState(state);
    }
}

How to reduce gas costs during synchronization?

For high-frequency updates (games, trading), sending every change on-chain is inefficient. The right architecture is batching. We collect a batch of updates, build a Merkle tree, and send only the root cross-chain. This reduces gas costs by up to 90% compared to individual sending. Our system can handle up to 10,000 state updates per second.

class StateSyncWorker {
  private pendingUpdates: Map<string, PlayerState> = new Map();
  private syncInterval = 30_000;

  queueUpdate(playerId: string, state: PlayerState): void {
    this.pendingUpdates.set(playerId, state);
  }

  async flushBatch(): Promise<void> {
    if (this.pendingUpdates.size === 0) return;
    const batch = Array.from(this.pendingUpdates.entries());
    this.pendingUpdates.clear();
    const leaves = batch.map(([id, state]) => keccak256(abi.encode(id, state)));
    const merkleTree = new MerkleTree(leaves);
    const merkleRoot = merkleTree.getRoot();
    await stateSyncContract.submitBatch(merkleRoot, batch.length, timestamp);
    await batchStore.save(merkleRoot, batch);
  }

  async generateProof(playerId: string, merkleRoot: string): Promise<MerkleProof> {
    const batch = await batchStore.load(merkleRoot);
    const leaf = keccak256(abi.encode(playerId, batch.get(playerId)));
    return merkleTree.getProof(leaf);
  }
}

On the destination chain, only the Merkle root (one bytes32) is stored. Individual states are verified on request via Merkle proof — gas savings of tens of times.

Toolset

Category Tools
Messaging LayerZero V2, Axelar GMP, Wormhole (Solana+EVM)
ZK proofs Herodotus (storage proofs), Succinct Telepathy (light client)
Indexing The Graph (multi-chain subgraph)
Monitoring Custom worker + alerting on message delivery failures
Testing Foundry with fork + mock messaging

What is included in the work

Detailed list of stages
  • Architectural design — choosing the messaging stack, calculating finality and gas, defining idempotency patterns.
  • Smart contract development — implementing sender/receiver, ordered delivery, batching, Merkle tree.
  • Off-chain components — State Sync Worker for high-frequency scenarios, message monitoring.
  • Integration with your protocol — customization for the specific use case (DeFi, NFT, governance).
  • Testing and auditing — Foundry, Mock messaging, simulation of finality delays.
  • Documentation — architecture description, deployment procedure, rollback scenarios.
  • Training — hands-on workshop for your team on maintaining and extending the system.
  • Access — to monitoring dashboards and alerting systems.
  • Post-launch support — monitoring, hotfixes, updates during hard forks.

Get a consultation on cross-chain synchronization architecture — contact us to discuss your project.

Timeline estimates and pricing

  • Basic synchronization (two chains, Axelar, ordered delivery) — 3–4 weeks, $20k–$30k.
  • Merkle-batched sync with off-chain worker — 8–12 weeks, $50k–$80k.
  • Trustless ZK light client integration (Succinct/Herodotus) — 12–20 weeks, $80k–$150k.

Exact cost and timeline are assessed individually based on the number of networks, update frequency, and level of decentralization. Contact us for a preliminary estimate.

Cross-Chain Bridge Development: Architecture, Risks, and Implementation

We develop cross-chain bridges and cross-chain solutions end-to-end. We know how to avoid disasters. A few years ago, the Binance BNB Chain bridge lost $570M — the attacker forged a Merkle proof in BSC's native bridge. That same year, Wormhole lost $320M: guardian signature verification was bypassed through a bug in Solana's secp256k1 program. Ronin Bridge — $625M. These are not coincidences. Bridges are the most attacked infrastructure in Web3 because they aggregate liquidity and have complex cross-chain verification logic.

Why Do Bridges Break? Three Architectural Classes of Vulnerabilities

Finality and Reorg Issues. Ethereum has probabilistic finality before The Merge and economic finality after (2 epochs, ~12 minutes). Bitcoin — ~6 blocks (~60 minutes). Solana — ~400ms. If a bridge mints wrapped tokens on the destination chain immediately after 1-2 blocks on the source — a reorg of 3+ blocks allows the attacker to obtain tokens on the destination while the source transaction is reverted. Correct protection: wait for finality confirmation specific to each chain. For Ethereum — 64+ blocks (2 epochs). Not one block.

Signature Verification. Most bridges use a multisig committee or threshold signature: N out of M validators must sign the event from the source chain. Wormhole used 13 out of 19 guardians. The attack was not on the keys themselves — the attacker found a vulnerability in the signature verification code on Solana, where an outdated sysvar account was accepted as valid without verification. On-chain signature verification is harder than it seems.

Lock-and-Mint vs Burn-and-Mint. In the lock-and-mint model, original tokens are locked in a contract on the source chain, and wrapped tokens are minted on the destination. The source contract is a honeypot: all locked TVL is there. One bug in the unlock logic — and all funds are available to the attacker without needing to do anything on the destination chain. Native burn-and-mint (like Circle CCTP for USDC) is safer: no locked pool.

How to Choose a Messaging Layer for Your Project?

LayerZero — a protocol for arbitrary message passing between chains. Not a bridge itself, but infrastructure for building bridges and omnichain applications.

Architecture: Endpoint contract on each chain, Executor (delivers messages to the destination chain), DVN (Decentralized Verifier Network — verifies the transaction fact on the source chain).

Source chain:
  OApp.send() → Endpoint.send() → [emits packet event]

Destination chain:
  DVN verifies packet hash → Executor calls Endpoint.deliver() → OApp.lzReceive()

In v2, the developer chooses DVNs: official (LayerZero Labs, Google Cloud, Polyhedra), or custom. One can configure required DVN + optional DVN: a message is accepted only if all required DVNs confirm. This allows building bridges with different trade-offs between security and speed.

OApp (Omnichain Application) — the base contract for integration. Inherit OApp, implement _lzSend and _lzReceive. For token bridges — OFT (Omnichain Fungible Token) standard out of the box does burn-on-source / mint-on-destination.

Wormhole uses a network of 19 guardians (large companies like Jump Crypto, Everstake, etc.), each signing observed events. Threshold — 13 out of 19. VAA (Verified Action Approval) — a signed message that is accepted on the destination chain.

Main difference from LayerZero: Wormhole has native support for non-EVM chains: Solana, Aptos, Sui, Algorand, Near. For projects needing a bridge between Ethereum and Solana — Wormhole is often the only production-ready option.

After the exploit, Wormhole added Native Token Transfers (NTT) — an architecture without a locked pool, similar to CCTP. NTT + Hub-and-Spoke model: redundant liquidity is not accumulated on one chain.

Relay Architecture and Light Client Verification

Relay-based bridges (IBC in Cosmos ecosystem, Succinct's Telepathy) verify the source chain's state via a light client on the destination chain. For EVM→EVM: a contract on Ethereum stores and verifies BLS signatures of the source chain's blocks.

ZK-bridges are the next level. Succinct, Polyhedra zkBridge, Electron Labs generate a ZK-proof of the correctness of the source chain's consensus. On the destination chain, the proof is verified, not the validator signatures. Removes trust in the committee. But ZK-proof verification is gas-expensive — from 200k to 500k gas on Ethereum L1 depending on the proof system. A ZK-bridge is safer than a relay-based bridge but requires 2-3 times more gas for verification.

Characteristic LayerZero Wormhole IBC (Cosmos) ZK-bridge
EVM support All EVM + Solana, Aptos All EVM + Solana, Aptos, Sui Cosmos chains Growing
Trust model DVN (configurable) 13/19 guardians Light client ZK proof
Latency 1-5 min 1-5 min ~30 sec 5-30 min
Gas for verification ~100-150k ~150-200k ~200-300k 200-500k

What Does Cross-Chain Bridge Development Include?

We implement the project turnkey and deliver a complete set of results. Our clients receive:

Stage Result
Analysis and architecture selection Technical specification, rationale for messaging layer choice
Smart contract design Specification, flow diagrams, trust model description
Development and testing Source code, unit/integration tests, cross-chain scenario simulation
Security audit External auditor report, fixed vulnerabilities
Deployment and monitoring Mainnet contracts, alert dashboard, operations documentation
Post-launch support 3 months warranty support, operations assistance

Implementation: What to Consider Before the First Line of Code

Mandatory components for any production bridge:

Pauser. Emergency pause function, called by multisig or automatically upon anomaly detection (suspicious volume, atypical call sequence). Most hacked bridges did not have or did not use a pauser in time.

Rate limiting. Limit output volume per time interval. If an attacker drains the bridge — rate limit gives time to react. Implementation: transferVolume[currentEpoch] += amount; require(transferVolume[currentEpoch] <= epochLimit).

Finality checks. Specific to each chain. Not "wait 1 block", but use finality API or wait for required number of confirmations.

Relayer monitoring. An autonomous service that monitors the state of both bridge sides. If a message is sent but not delivered within N minutes — alert. If locked balance diverges from totalSupply of wrapped token — critical alert.

Timeline and Cost

A simple ERC-20 bridge on top of an existing messaging layer (LayerZero OFT or Wormhole NTT) — 4-8 weeks including testing and audit. A custom bridge with own verification, multi-chain support, rate limiting, monitoring — 12-24 weeks. A ZK-bridge with custom proof circuits — from 6 months.

Bridge audit takes longer than a standard DeFi protocol audit: cross-chain scenarios, finality edge cases, reorg attacks must be tested. Minimum 3-4 weeks for a production-grade solution.

Cost is calculated individually after workload assessment. We have been working since 2018 and have completed 15+ projects in blockchain infrastructure. Contact us — we will evaluate your project and propose the optimal bridge architecture.