---
title: "Off-chain Orders in Rust"
url: "/docs/build-on-signet/signet-to-ethereum/rust-orders/index.md"
description: "Create Signet Orders in Rust"
---
# Off-chain Orders in Rust

This page will walk you through creating and submitting off-chain Orders using
Rust and the Signet SDK.

The [Orders](https://github.com/init4tech/zenith/blob/main/src/orders/) contract enables trustless, cross-chain asset swaps between
Signet and Ethereum. Signet nodes listen for Order and Filled events,
and ensure that all transactions that emit Orders have corresponding Fills
executed on the destination chain in the same block.

Order events are emitted on Signet, while Filled events may be emitted
on either Ethereum or Signet. Off-chain orders are pre-signed, using
[Permit2](https://docs.uniswap.org/contracts/permit2/overview), and may be executed by a third-party filler, allowing users to
perform gasless swaps.

> **Set competitive prices on your orders:** Signet Orders guarantee that if their Outputs are not Filled, no transaction
will be executed on Signet. However, there is no guarantee that any searcher
will choose to Fill your Order. Make sure to set competitive prices on your
orders to ensure they are filled!

## Setup

Install the required Signet crates

```bash
cargo add signet-zenith
cargo add signet-constants
cargo add signet-types
cargo add signet-tx-cache
```

Ensure your account has approved [Permit2](https://docs.uniswap.org/contracts/permit2/overview) to spend your input tokens.

Consult the [Parmigiana Quickstart](/docs/build-on-signet/parmigiana/index.md) guide for contract addresses and RPC endpoints.

## Creating an Order

The [signet-types](http://docs.rs/signet-types/latest/signet_types/) crate provides a simple order builder via the
[UnsignedOrder](https://docs.rs/signet-types/latest/signet_types/signing/order/struct.UnsignedOrder.html) struct, which can be used to build orders. We can
start by creating a simple order that swaps 1 WETH on Signet for 1 WETH on
Ethereum:

```rust
use signet_types::signing::order::{UnsignedOrder};
use signet_constants::parmigiana as constants;

let mut order = UnsignedOrder::default()
    .with_input(
        constants::RU_WETH,
        U256::from(1e18), // 1 WETH
    ).with_output(
        constants::HOST_WETH,
        U256::from(1e18),
        your_address,
        1, // Ethereum mainnet
    );
```

The `UnsignedOrder` struct also provides methods to sign orders, using any
alloy signer. The signer requires that you provide the `constants` object, so
that the permit2 signer can correctly derive the domain separator.

```rust
use signet_types::signing::order::{UnsignedOrder};
use signet_constants::parmigiana as constants;

let signed = UnsignedOrder::default()
    .with_input(token_address, amount)
    .with_output(token_address, amount, recipient, chain_id)
    .with_chain(constants)
    .with_nonce(permit2_nonce)
    .sign(&signer).await?;
```

## Submitting an Order

Once signed, the order can be submitted to the Signet network via the Signet tx
cache. The tx cache makes the Order available to Searchers, who will include it
in execution bundles.

```rust
use signet_tx_cache::TxCache;

let tx_cache = TxCache::parmigiana();
tx_cache.forward_order(signed_order).await?;
```

## Using OrderSender

For long-running services or bots, the
[`signet-orders`](https://docs.rs/signet-orders/latest/signet_orders/) crate
provides [`OrderSender`](https://docs.rs/signet-orders/latest/signet_orders/struct.OrderSender.html)
— a reusable struct that wraps signing and submission into a single interface.

```bash
cargo add signet-orders
```

`OrderSender` is generic over any alloy
[`Signer`](https://docs.rs/alloy/latest/alloy/signers/trait.Signer.html) and any
[`OrderSubmitter`](https://docs.rs/signet-orders/latest/signet_orders/trait.OrderSubmitter.html)
backend. A ready-made `OrderSubmitter` implementation is provided for `TxCache`.

```rust
use signet_constants::parmigiana;
use signet_orders::OrderSender;
use signet_tx_cache::TxCache;

// Any alloy Signer works: LocalSigner, AwsSigner, LedgerSigner, etc.
let signer = /* your signer */;

let order_sender = OrderSender::new(
    signer,
    TxCache::parmigiana(),
    parmigiana::system_constants(),
);

// Sign and submit in one call
let signed = order_sender.sign_and_send_order(order).await?;
```

You can also sign and send separately for more control:

```rust
let signed = order_sender
    .sign_unsigned_order(
        UnsignedOrder::default()
            .with_input(token_address, amount)
            .with_output(token_address, amount, recipient, chain_id),
    )
    .await?;

// Submit when ready
order_sender.send_order(signed).await?;
```

If you need to submit orders somewhere other than the tx cache, implement the
`OrderSubmitter` trait:

```rust
use signet_orders::OrderSubmitter;
use signet_types::SignedOrder;

struct MySubmitter;

impl OrderSubmitter for MySubmitter {
    type Error = MyError;

    async fn submit_order(&self, order: SignedOrder) -> Result {
        // Forward the order to your backend
        todo!()
    }
}
```

For on-chain order creation, check out [Solidity Orders](/docs/build-on-signet/signet-to-ethereum/on-chain-orders/index.md).
