# What Is the Relayer Service in Fuel Core for Cross-Chain Communication?

> Discover the relayer service in Fuel Core. It secures cross-chain communication by bridging Fuel with data-availability layers like Ethereum. Learn how it processes finalized events.

- Repository: [Fuel Labs/fuel-core](https://github.com/FuelLabs/fuel-core)
- Tags: deep-dive
- Published: 2026-03-06

---

**The relayer service in Fuel Core acts as a secure bridge between Fuel's execution layer and external data-availability layers like Ethereum, ensuring that only finalized cross-chain events such as messages and forced transactions are processed into Fuel blocks.**

The relayer service is a critical component of the [Fuel Labs `fuel-core`](https://github.com/FuelLabs/fuel-core) repository that enables secure cross-chain communication by synchronizing the Fuel execution layer with external data-availability (DA) layers. Currently implemented to interface with Ethereum contracts, this service ensures that cross-chain messages and forced-inclusion transactions are only accepted after achieving sufficient finality, protecting the integrity of the Fuel blockchain state.

## Core Responsibilities of the Relayer Service

### Tracking DA-Layer Finality

The relayer monitors the DA layer's block height to determine finality before accepting any cross-chain data. For Ethereum, this means waiting approximately **12 minutes** (two Ethereum epochs) before considering blocks final. Only events from finalized blocks are deemed safe for inclusion in Fuel blocks, preventing reorg-related vulnerabilities that could compromise state consistency.

*Source: [`crates/services/relayer/README.md`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/relayer/README.md) lines 9-12.*

### Downloading and Persisting Cross-Chain Events

When the relayer detects that Fuel is behind the DA layer, it executes a background task to pull **log events** from the DA contract. These events include messages representing token deposits on Ethereum and forced-inclusion transactions that must be executed on Fuel. The relayer stores these events in the Fuel database, making them available to block producers, importers, and executors.

*Source: [`crates/services/relayer/README.md`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/relayer/README.md) lines 20-24.*

### Exposing the Event API

The service defines a unified `Event` enum in `fuel_core::services::relayer` that abstracts two primary event types: `Message` events for cross-chain asset transfers and `RelayedTransaction` events for forced L1 transaction inclusion. Consumers query the relayer for events at specific DA heights through a consistent interface, regardless of the underlying DA layer implementation.

*Source: [`crates/types/src/services/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/types/src/services/relayer.rs) lines 13-31.*

## Architectural Integration

### Hexagonal Architecture Design

The relayer is implemented as a distinct **domain** (designated `RS` in the architecture documentation) that exposes only **ports** defined in `fuel_core_relayer::ports`. Concrete adapters reside in the top-level `fuel-core` crate, specifically in `service::adapters::relayer`. This hexagonal architecture isolates core business logic from external networking concerns, allowing the relayer to remain agnostic of specific DA layer implementations while maintaining testability.

*Source: [`docs/architecture.md`](https://github.com/FuelLabs/fuel-core/blob/main/docs/architecture.md) lines 82-86 and [`crates/fuel-core/src/service/adapters/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/service/adapters/relayer.rs).*

### WASM-Compatible Port

For execution within the sandboxed WASM environment, the relayer provides `WasmRelayer`, which forwards calls to host functions including `relayer_enabled` and `relayer_get_events`. This enables the upgradable WASM executor to access cross-chain events without breaking sandbox security boundaries, ensuring consistent behavior between native and WASM execution contexts.

*Source: [`crates/services/upgradable-executor/wasm-executor/src/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/wasm-executor/src/relayer.rs) lines 8-18.*

## Practical Implementation Examples

### Querying Events from the Database Adapter

The native database adapter implements event retrieval for the relayer domain. Below is how you would query events at a specific DA block height:

```rust
use fuel_core::{
    service::adapters::relayer::Database,
    types::services::relayer::Event,
    blockchain::primitives::DaBlockHeight,
};

fn fetch_events(db: &Database<Relayer>, height: DaBlockHeight) -> anyhow::Result<Vec<Event>> {
    // get_events is implemented in the Relayer adapter
    db.get_events(&height)
}

```

*Implementation reference*: `Database<Relayer>::get_events` in [`crates/fuel-core/src/service/adapters/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/service/adapters/relayer.rs) lines 36-47.

### Using the WASM Executor Port

When running inside the WASM executor, access the relayer through the `WasmRelayer` struct which delegates to host functions:

```rust
use fuel_core_executor::ports::RelayerPort;
use fuel_core_types::services::relayer::Event;
use fuel_core_types::blockchain::primitives::DaBlockHeight;

let relayer = WasmRelayer; // from wasm-executor crate
if relayer.enabled() {
    let da_height = DaBlockHeight::new(12345);
    let events: Vec<Event> = relayer.get_events(&da_height)?;
    // Process Message or RelayedTransaction events...
}

```

*Reference*: [`crates/services/upgradable-executor/wasm-executor/src/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/wasm-executor/src/relayer.rs) lines 8-18.

### Wiring the Relayer into a Service Instance

To instantiate the relayer within the Fuel Core service architecture, use the `Instance` builder pattern:

```rust
use fuel_core::service::Instance;
use fuel_core_relayer::RelayerHandle;

let relayer_handle = RelayerHandle::new(config)?;
let instance = Instance::new()
    .add_relayer(relayer_handle)?
    .start_all()?;

```

*Wiring logic* is defined in `Instance::add_relayer` within [`crates/services/upgradable-executor/src/instance.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/src/instance.rs) around lines 400-425.

## Key Source Files

Understanding the relayer service requires familiarity with these specific files in the `FuelLabs/fuel-core` repository:

- **[`crates/services/relayer/README.md`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/relayer/README.md)** – High-level documentation explaining finality logic (12-minute Ethereum finalization) and background task behavior.

- **[`crates/types/src/services/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/types/src/services/relayer.rs)** – Definition of the `Event` enum (lines 13-31) that abstracts `Message` and `RelayedTransaction` types.

- **[`crates/fuel-core/src/service/adapters/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/service/adapters/relayer.rs)** – Database adapter implementation providing `get_events` functionality (lines 36-47).

- **[`docs/architecture.md`](https://github.com/FuelLabs/fuel-core/blob/main/docs/architecture.md)** – Hexagonal architecture documentation showing the Relayer Service (`RS`) domain and its ports (lines 82-86).

- **[`crates/services/upgradable-executor/wasm-executor/src/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/wasm-executor/src/relayer.rs)** – WASM-compatible relayer port forwarding to host functions (lines 8-18).

- **[`crates/services/upgradable-executor/src/instance.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/src/instance.rs)** – Service wiring logic around lines 400-425.

## Summary

The relayer service in Fuel Core serves as the critical bridge between Fuel's execution layer and external data-availability layers like Ethereum. Key takeaways include:

- **Finality enforcement**: The relayer waits for approximately 12 minutes (two Ethereum epochs) before accepting DA layer events, protecting against blockchain reorganizations.

- **Event abstraction**: Through the `Event` enum in `fuel_core::services::relayer`, the service unifies `Message` deposits and `RelayedTransaction` forced inclusions behind a consistent API.

- **Hexagonal architecture**: The relayer domain exposes only ports (`fuel_core_relayer::ports`), with concrete adapters living in [`fuel-core/src/service/adapters/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/fuel-core/src/service/adapters/relayer.rs), ensuring clean separation from networking concerns.

- **WASM compatibility**: `WasmRelayer` enables sandboxed execution environments to access cross-chain events via host functions without compromising security boundaries.

## Frequently Asked Questions

### How does the relayer service handle blockchain reorgs on the DA layer?

The relayer service mitigates reorganization risks by enforcing a **finality period** of approximately 12 minutes (two Ethereum epochs). It only downloads and persists events from DA layer blocks that have achieved this finality threshold, ensuring that once events are incorporated into Fuel blocks, they cannot be invalidated by external chain reorganizations.

### What types of cross-chain events does the relayer process?

According to the `Event` enum defined in [`crates/types/src/services/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/types/src/services/relayer.rs), the relayer processes two primary event types: **Message** events representing token deposits and other communications from Ethereum, and **RelayedTransaction** events representing forced-inclusion transactions that must be executed on the Fuel chain regardless of standard transaction validation rules.

### Why does Fuel Core use hexagonal architecture for the relayer?

Fuel Core implements the relayer as a distinct domain (`RS`) within its hexagonal architecture to enforce **separation of concerns**. By exposing only abstract ports in `fuel_core_relayer::ports` while placing concrete networking adapters in the top-level `fuel-core` crate, the system keeps core business logic isolated from external DA layer specifics. This design enables testing with mock adapters and supports future DA layer implementations without modifying domain logic.

### Can the relayer service operate within the WASM executor?

Yes, the relayer service provides a **WASM-compatible port** through `WasmRelayer` in [`crates/services/upgradable-executor/wasm-executor/src/relayer.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/upgradable-executor/wasm-executor/src/relayer.rs). This implementation forwards relayer calls to host functions (`relayer_enabled`, `relayer_get_events`), allowing the sandboxed WASM executor to access cross-chain events without breaking security boundaries or requiring direct network access within the WASM environment.