cross-ping: The Asymmetric Bridge Between Wasm Actors and EVM

A masterclass in bidirectional messaging using ZK-proofs, Light Clients, and the Actor Model to link the Vara Network with Ethereum.

• View on GitHub • More from gear-foundation

An illustration of a bridge connecting a massive, slow-moving stone gear system to a swarm of fast-moving hummingbirds, representing the connection between Ethereum and Vara.
Bridging synchronous EVM contracts with asynchronous Wasm actors requires distinct trust models for each direction.

Key Takeaways

The Trust Gap

The holy grail of blockchain has always been seamless interoperability. Most bridges, however, are black boxes operated by centralized multisig wallets. The cross-ping repository offers a bare-metal look at cross-chain messaging that uses two entirely different trust models to bridge Ethereum’s heavy computation with Vara’s high-speed Actor Model.

Bridging to Ethereum is a different beast than bridging from it. To save on exorbitant gas costs, the Vara-to-Ethereum path relies on Zero-Knowledge inclusion proofs. Conversely, the Ethereum-to-Vara path leverages Vara's WebAssembly efficiency to run an on-chain Light Client.

Cross-chain communication can seem complex, but at its core, it’s about securely moving messages and value between independent blockchains. To make this process clear and approachable, a simple Ping-Pong application is used as the most illustrative example, showing step by step how secure cross-chain messaging works on top of the Vara ↔ Ethereum Bridge.

Gear Foundation, Author Organization · Vara → Ethereum App Guide

Ethereum as a Remote Actor

Vara is built on the Actor Model. In this paradigm, a smart contract on Ethereum is not a foreign entity. It is simply an addressable actor that responds to a message request.

The bidirectional message flow from an EVM contract to a Wasm actor and back.

When a Wasm actor wants to ping Ethereum, it does not make a synchronous call. It sends a payload to a built-in system actor and goes to sleep. The bridge handles the delivery asynchronously without blocking the rest of the network.

Race Conditions in the Relayer

The connective tissue between these networks is a Node.js relayer. Relayers are permissionless pieces of infrastructure that monitor state changes and submit proofs to the destination chain.

The Vara-to-Ethereum relayer faces a classic distributed systems problem. It must wait for both an application-level event from the Sails framework and a system-level bridge event before it can move. It resolves this race condition by caching the first event and triggering the relay only when a matching pair is verified.

A close-up of a mechanical sorter dropping different shaped tokens into a single funnel that only opens when a matching pair is present.
The Node.js relayer acts as a synchronization funnel for application and system events.

Architecture: ZK vs. Light Client

The two directions of the bridge are fundamentally asymmetric. One path proves state inclusion via Merkle roots, while the other tracks the Beacon Chain head to verify finality.

FeatureVara to EthereumEthereum to Vara
MechanismZK-Inclusion ProofOn-chain Light Client
Verification EnvironmentEVM (expensive gas)Wasm Sandbox (cheap compute)
LatencyTied to batch proof generationTied to Beacon Chain finality

How a cross-chain message is cryptographically proven via Merkle inclusion.

The Developer Experience with Sails

Writing raw WebAssembly actors can be daunting. The Gear ecosystem abstracts this complexity using the Sails framework, allowing developers to write decoupled, service-oriented Rust code.

WSJ hedcut-style portrait of a Gear Foundation contributor.

The framework automatically generates an Interface Definition Language (IDL) file. This ensures that the TypeScript relayer and the underlying Rust program never drift out of sync, turning complex cross-chain logic into standard method calls.

#[sails_rs::program]
impl PingReceiverProgram {
    #[service]
    pub fn submit_receipt(&mut self, receipt: Receipt) {
        // Process the validated Ethereum event
        self.state.process(receipt);
    }
}