Skip to main content

Off-chain Orders in Rust

View as Markdown

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

The 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, and may be executed by a third-party filler, allowing users to perform gasless swaps.

Setup

Set up your Rust project

cargo new my_cool_app --bin

Install the required Signet crates

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

Ensure your account has approved Permit2 to spend your input tokens.

Consult the Pecorino Quickstart guide for contract addresses and RPC endpoints.

Creating an Order

The signet-types crate provides a simple order builder via the UnsignedOrder 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:

use signet_types::signing::order::{UnsignedOrder};
use signet_constants::pecorino 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.

use signet_types::signing::order::{UnsignedOrder};
use signet_constants::pecorino 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.

use signet_tx_cache::TxCache;

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

For on-chain order creation, check out Solidity Orders.

Start typing to search documentation...