xenith-core 0.1.0

Transport-agnostic traits, types, and errors for xenith cross-chain state sync
Documentation

xenith

Cross-chain state sync for Rust — transport-agnostic, divergence-explicit, bot-first.

The Problem

Multi-chain protocols share state across EVM networks using ad-hoc messaging (LayerZero, CCIP, Axelar), but there is no standardized primitive that sits above those transports. Every team ends up rewriting the same glue: serializing state updates into message payloads, tracking in-flight message IDs, comparing observed values across chains, and deciding what to do when two chains disagree. The absence of a shared abstraction means teams are locked into a single messaging protocol from day one, and divergence bugs — where different chains hold silently inconsistent state — are caught only when a liquidation misfires or an arbitrage reverts.

What xenith is

xenith is a transport-agnostic, Rust-native library that treats cross-chain state sync as a first-class primitive. You plug in any messaging transport (LayerZero, CCIP, or your own), and xenith handles local persistence, message dispatch, and read-back under a ReadStrategy you choose. Diverged state is never silently resolved — SyncStatus::Diverged surfaces to the caller who is always in control of conflict resolution. The MultiChainReader issues parallel RPC reads across chains so keeper bots and arbitrage engines get consistent snapshots without blocking on sequential calls.

Quick Start

Add the crates you need to Cargo.toml:

[dependencies]
xenith-core      = "0.1"
xenith-layerzero = "0.1"
xenith-sync      = "0.1"

Push a state value from Ethereum to Arbitrum, then read it back:

use std::sync::Arc;
use bytes::Bytes;
use xenith_core::{ChainId, InMemoryStore, ReadStrategy, StateKey};
use xenith_layerzero::LayerZeroTransport;
use xenith_sync::{SyncConfig, SyncEngine};

#[tokio::main]
async fn main() -> xenith_core::Result<()> {
    // LayerZero endpoint IDs: Ethereum mainnet = 30101, Arbitrum = 30110
    let transport = Arc::new(LayerZeroTransport::new(
        [0u8; 20], // endpoint contract address on the source chain
        vec![
            (ChainId::from(1),     30101),
            (ChainId::from(42161), 30110),
        ],
    ));

    let engine = SyncEngine::new(
        transport,
        Arc::new(InMemoryStore::default()),
        SyncConfig::default(),
    );

    let key = StateKey::new("uniswap", "pool", "0xabc123");

    // Store locally and broadcast to Arbitrum.
    let receipt = engine
        .push(
            key.clone(),
            Bytes::from_static(b"price=3400"),
            vec![ChainId::from(42161)],
            ChainId::from(1), // source chain
            None,             // no on-chain metadata needed for this push
        )
        .await?;

    println!("dispatched to {} chain(s)", receipt.successes.len());

    // Read back; Ethereum is the declared source of truth.
    let state = engine
        .read(key, ReadStrategy::SourceOfTruth(ChainId::from(1)))
        .await?;

    println!("status: {:?}", state.status); // SyncStatus::Synced
    println!("data:   {:?}", state.value.data);

    Ok(())
}

Crate Overview

Crate Description
xenith-core Transport-agnostic traits, domain newtypes, XenithError, InMemoryStore, and ConflictResolver. No external deps beyond alloy-primitives, async-trait, thiserror, and bytes.
xenith-layerzero LayerZero v2 MessagingTransport implementation; stub behaviour by default, real endpoint calls behind the live feature flag.
xenith-sync SyncEngine — the primary API surface. Composes a transport and a store to provide push, read, and resolve.
xenith-read MultiChainReader — issues parallel RPC reads across many chains simultaneously and reports storage-slot divergence.

Transport Support

Transport Status Notes
LayerZero v2 v0.1 Stub impl ships now; live feature gates real endpoint calls
Chainlink CCIP v0.2 planned xenith-ccip crate
Axelar v0.3 planned xenith-axelar crate

Contributing

PRs are welcome. Before submitting, run:

cargo clippy --workspace -- -D warnings
cargo fmt
cargo test --workspace

All three must pass clean. Clippy warnings are treated as errors; the formatter is non-negotiable. If you are adding a new transport, implement the transport_compliance_tests! macro suite from xenith-core to verify conformance.

Stability: xenith follows Semantic Versioning. While on 0.x.y, minor version bumps may include breaking changes. Patch bumps are always backwards compatible. Subscribe to releases on GitHub to be notified of breaking changes.

Publishing: Crates are published manually by the maintainer after each release tag. To publish for the first time, the semver CI job must be initialized: tag a v0.0.1 release with the current codebase as the baseline before making any API changes.