Documentation/Build on Signet/To Ethereum
Off-chain Orders in Rust
Create Signet Orders in Rust
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
Install the required Signet crates
cargo add signet-zenith
cargo add signet-constants
cargo add signet-types
cargo add signet-tx-cacheEnsure your account has approved Permit2 to spend your input tokens.
Consult the Parmigiana 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::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.
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.
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 crate
provides OrderSender
— a reusable struct that wraps signing and submission into a single interface.
cargo add signet-ordersOrderSender is generic over any alloy
Signer and any
OrderSubmitter
backend. A ready-made OrderSubmitter implementation is provided for TxCache.
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:
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:
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<(), Self::Error> {
// Forward the order to your backend
todo!()
}
}For on-chain order creation, check out Solidity Orders.