Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cross-lattice coordination

audience: contributors

A lattice is one end-to-end block-building deployment for one EVM chain. In practice operators and integrators will want more than one: a mainnet lattice and a testnet lattice, an L1 lattice and an L2 lattice, lattices for sibling rollups that share searchers. This chapter describes how lattices on the same mosaik universe coordinate without giving up the per-lattice trust boundaries.

The reader is assumed to have read topology-intro, architecture, organisms, and composition.

What cross-lattice means

Two lattices on the same mosaik universe are simply two LatticeConfigs whose instance names differ and whose per-organism Configs therefore derive disjoint GroupIds, StreamIds, and StoreIds. Everything the topology intro — Shared universe page says about zipnet deployments coexisting applies unchanged to full lattices.

“Cross-lattice coordination” means something stronger: an integrator agent, or an organism inside one lattice, reads from or writes to a second lattice’s public surface, coordinated by slot or by intent.

Three use cases motivate this section:

  1. Cross-chain searchers. One searcher agent bids on L1 ethereum.mainnet and L2 unichain.mainnet simultaneously. Their bundles may span both chains (sell on L1, buy on L2 in a coordinated pair).
  2. Cross-chain order flow. A wallet submits an intent on base.mainnet that resolves on multiple chains (swap X on Base, receive Y on OP). The intent needs to reach several lattices’ zipnet / unseal pools.
  3. Shared tally. Attribution for an MEV-Share-style refund spans multiple lattices (a backrun on L1 attributed partially to an L2-originating order).

None of these require a “cross-lattice Group” or a seventh organism. They are all implementable as integrators holding multiple LatticeConfigs, or as organisms reading from adjacent lattices’ public surfaces. The mosaik universe is shared; the work is in specifying the integrator / organism’s driver shape.

Shape 1: integrator spans multiple lattices

The simplest shape. The integrator compiles in N LatticeConfigs and binds organism handles against each from one Arc<Network>.

use std::sync::Arc;
use mosaik::Network;
use builder::{LatticeConfig, UNIVERSE};

const ETH_MAINNET:       LatticeConfig = /* ... */;
const UNICHAIN_MAINNET:  LatticeConfig = /* ... */;
const BASE_MAINNET:      LatticeConfig = /* ... */;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let network = Arc::new(Network::new(UNIVERSE).await?);

    // One searcher, three lattices.
    let eth_offer  = offer::Offer::<Bundle>::bid(&network, &ETH_MAINNET.offer     ).await?;
    let uni_offer  = offer::Offer::<Bundle>::bid(&network, &UNICHAIN_MAINNET.offer).await?;
    let base_offer = offer::Offer::<Bundle>::bid(&network, &BASE_MAINNET.offer    ).await?;

    // Read outcomes to close the loop.
    let eth_wins = offer::Offer::<Bundle>::outcomes(&network, &ETH_MAINNET.offer     ).await?;
    let uni_wins = offer::Offer::<Bundle>::outcomes(&network, &UNICHAIN_MAINNET.offer).await?;

    // The driver pairs cross-chain bundles by correlator and
    // submits to both lattices in wall-clock — but NOT in
    // consensus. A partial win (one chain accepts, the other
    // does not) is a normal outcome the driver must handle.
    // ...
    Ok(())
}

What integrators get out of this:

  • One mosaik endpoint, one DHT record, one gossip loop. Peer discovery is shared across lattices; adding a third lattice costs no additional network resources.
  • Independent bidding per lattice. Each lattice’s offer auction commits on its own cadence; the searcher agent can withdraw a partial bid on one lattice if the paired lattice rejects.
  • No cross-chain atomic guarantee. The integrator must be willing to tolerate partial outcomes — sell-leg fills on one chain, buy-leg does not on the other. This is a searcher-level risk-management problem, not a protocol-level one. The alternative — cross-lattice atomic commit — is explicitly out of scope for this topology. See topology-intro — No cross-Group atomicity.

Shape 2: organism reads across the lattice boundary

An organism in lattice A subscribes to an organism’s public surface in lattice B. Concretely: tally in unichain.mainnet reads zipnet::Broadcasts from ethereum.mainnet so that a refund for an L2 block can credit an L1-originating transaction.

This is legal under the topology because:

  • Both lattices share the same universe, so the subscription just works as a mosaik Collection read against a StoreId derived from the other lattice’s Config.
  • The cross-lattice read is authenticated by the other lattice’s ACL. If ethereum.mainnet’s zipnet::Broadcasts is readable by any lattice ticket holder, the unichain.mainnet::tally committee members hold tickets for both lattices and the read succeeds.
  • The tally state machine in unichain.mainnet still commits its attribution inside its own Group. The cross-lattice read is input, not commit. No cross-Group atomicity is introduced.

What the organism operator has to wire up:

  1. unichain.mainnet::tally committee members are admitted to ethereum.mainnet‘s zipnet::Broadcasts via a ticket. (Ticket granting is an operator-level agreement between the two lattices’ operators, out of band.)
  2. unichain.mainnet::tally’s Config folds in the ethereum.mainnet::LatticeConfig fingerprint it reads from. This makes a mis-paired unichain.mainnet::tally — one compiled against a different ethereum.mainnet — derive a different GroupId and fail to bond with its own peers, not silently misattribute.

This is the machinery that lets MEV-Share across chains work without a central coordinator.

Shape 3: a “bridge” organism

When the coordination is symmetric (both lattices read from and write to a shared fact), the right answer is a seventh organism — one that lives outside any lattice and whose role is to provide the shared fact.

Example: a cross-chain intent router organism that sits above multiple lattices, reads from each one’s zipnet::UnsealedPool, and commits an IntentRouting collection that tells each lattice’s offer which cross-chain bundles are admissible.

A bridge organism is exactly one more organism, following exactly the same pattern:

  • Its own Config folds in the set of lattices it spans (by LatticeConfig fingerprint).
  • Its own GroupId is derived from that.
  • Its own public surface is one or two primitives (an Intents stream, an IntentRouting collection).
  • Its own committee is an operator-level deployment.

This proposal does not ship a bridge organism. It identifies the shape so that contributors extending the topology do not reinvent a second kind of cross-lattice coordination on top of the ones above.

What is explicitly not supported

Cross-lattice atomic commit

No primitive in this topology offers “commit both slot S on lattice A and slot S’ on lattice B or neither”. Two reasons:

  • Mosaik’s Raft variant does not support multi-Group transactions within a lattice, let alone across lattices. Inventing it here would reinvent the protocol we chose not to use at a level that would force every organism’s state machine to participate.
  • The business justification is thin. Cross-chain MEV in practice relies on searcher risk management (post-bond, posted collateral, on-chain HTLCs), not on builder-level atomic commit. Lattices provide a faithful pipeline; searchers structure their bundles to tolerate partial fills.

If a concrete use case for cross-lattice atomicity emerges, the right answer is a bridge organism whose state machine implements the atomic commit semantics the use case requires. See the roadmap.

Lattice registries

A cross-lattice directory collection — a Map<LatticeName, LatticeCard> listing known lattices — is explicitly not a core feature. The topology intro argument applies unchanged: lattices are operator-scoped, discovery is a compile-time LatticeConfig reference, and a registry would add its own ACL problem without buying anything an out-of-band handshake does not already provide. A devops-convenience directory may exist; it is never part of the binding path.

Cross-universe lattices

If two lattices live on different NetworkIds, they are on different mosaik universes and this chapter does not apply. The integrator has to hold two Network handles, pay for two discovery loops, and the shared-universe arguments all invert. The topology takes no position on whether that is desirable. If it is, do it; this book does not describe it.

L1 / L2 / rollup specialization

Three chain archetypes the lattice supports without new organisms:

  • L1 PBS (Ethereum mainnet). The reference shape. relay talks to the validator set’s MEV-Boost-compatible endpoints.
  • L2 rollup with centralized sequencer. relay talks to a single sequencer endpoint instead of a validator set. Operationally, the relay organism has one output target; its state machine is otherwise unchanged. tally watches the sequencer’s canonical chain rather than the L1 for inclusion.
  • L2 rollup with decentralized sequencer. relay talks to the sequencer’s leader rotation. tally still watches the canonical chain. The organism interfaces are the same.

In every case the lattice’s LatticeConfig carries a chain_id and the relay::Config carries a proposer_endpoint_policy parameter selecting the mode. That is the whole customization surface.

Cross-references