---
title: "Building with Orders"
url: "/updates/building-with-orders/index.md"
date: "2025-08-20"
description: "A practical guide to placing and filling cross-chain orders on Signet"
---
This guide walks through implementing cross-chain orders on Signet. By the end, you'll have working code for both sides of the order flow: creating orders as an application, and filling orders as a market participant.

**What you'll build:**
- Order creation: Express user intent through signed Permit2 structures
- Order filling: Compete to fulfill orders profitably
- Bundle coordination: Atomic execution across chains

**Prerequisites:**
- Rust development environment
- Funded wallet on [Parmigiana testnet](/docs/build-on-signet/parmigiana/index.md)
- Familiarity with [The Filler Economy](/updates/the-filler-economy/index.md) concepts

All code is available in [`signet-orders`](https://github.com/init4tech/signet-orders).

---

## Part 1: Creating Orders

Orders express cross-chain intent. A user says: "I'll give you X on Signet if you give me Y on Ethereum." Applications construct and sign these orders on behalf of users.

### The SendOrder Pattern

**Code: [`src/order.rs`](https://github.com/init4tech/signet-orders/blob/main/src/order.rs)**

```rust
impl SendOrder {
    /// Sign an order and submit it to the transaction cache
    pub async fn sign_and_send_order(&self, order: Order) -> Result {
        let signed = self.sign_order(order).await?;
        self.send_order(signed).await
    }

    /// Sign an order without submitting
    pub async fn sign_order(&self, order: Order) -> Result {
        // Build Permit2 authorization and sign
        // ...
    }

    /// Submit a pre-signed order to the transaction cache
    pub async fn send_order(&self, signed: SignedOrder) -> Result {
        self.tx_cache.forward_order(signed).await
    }
}
```

**What's happening:**
1. **Order construction**: Build the order specifying inputs (what user gives) and outputs (what user wants)
2. **Permit2 signing**: User approves token spend with a single signature (no separate approve tx)
3. **Submission**: Order goes to the transaction cache where Fillers discover it

### Order Structure

```rust
pub struct SignedOrder {
    pub permit: Permit2Batch,      // Single signature authorization
    pub outputs: Vec,      // What user wants to receive
}

pub struct Output {
    pub token: Address,            // Asset (e.g., WETH)
    pub amount: Uint,      // Amount
    pub recipient: Address,        // Where to send it
    pub chainId: u32,              // Which chain (1 = Ethereum)
}
```

Orders have a ~10 minute validity window. If no Filler accepts within that window, the order expires and nothing happens.

---

## Part 2: Filling Orders

Fillers are market participants who fulfill orders for profit. They provide the outputs users want and receive the inputs users offer.

### The Filler Pattern

**Code: [`src/filler.rs`](https://github.com/init4tech/signet-orders/blob/main/src/filler.rs)**

```rust
impl Filler {
    pub async fn fill(&self, orders: Vec) -> Result {
        // 1. Construct and sign Permit2 fills for destination chains
        let fills = self.construct_fills(&orders).await?;

        // 2. Build atomic bundle combining initiates and fills
        let bundle = self.build_signet_bundle(&orders, &fills).await?;

        // 3. Submit to Transaction Cache for builder inclusion
        self.tx_cache.submit_bundle(bundle).await
    }
}
```

**What's happening:**
1. **Construct fills**: Filler signs their side of the trade (providing outputs to user)
2. **Build bundle**: Combine order execution with fill execution
3. **Submit**: Bundle goes to builders for atomic inclusion

### Two Filling Strategies

**Aggregate execution** — All orders in one bundle:

```rust
pub async fn fill(&self, orders: Vec) -> Result {
    // Submit all Orders/Fills in single Bundle
    // Atomic: all succeed or none do
}
```

Pros: Gas efficient, can reuse capital across orders
Cons: Single failure breaks entire bundle

**Individual execution** — Each order in its own bundle:

```rust
pub async fn fill_individually(&self, orders: Vec) -> Result {
    // Submit each Order/Fill in separate Bundle
    // Independent: orders succeed or fail separately
}
```

Pros: Resilient, simple validation
Cons: Higher gas, can't optimize across orders

Choose based on your risk tolerance and order flow.

---

## Part 3: Bundle Construction

Orders and fills execute atomically through Signet's bundle system.

```rust
let bundle = SignetEthBundle {
    host_fills: Some(permit2_fills),    // Ethereum-side actions
    bundle: EthSendBundle {
        txs: signet_transactions,       // Signet-side transactions
        block_number: target_block,
        reverting_tx_hashes: vec![],    // No partial execution
    }
};
```

**Key properties:**
- **Block-specific**: Bundles target a specific block number
- **Atomic**: All transactions succeed or none do
- **Retry-able**: Failed bundles can target the next block

The `OrderDetector` in Signet's EVM enforces atomicity: order transactions only execute if corresponding fills exist.

---

## Part 4: Running the Example

The [`roundtrip`](https://github.com/init4tech/signet-orders/blob/main/bin/roundtrip.rs) example demonstrates the complete flow.

### Setup

**1. Configure environment:**

```bash
export CHAIN_NAME=parmigiana
export RU_RPC_URL=https://rpc.parmigiana.signet.sh/
export SIGNER_KEY=[your private key or AWS KMS key ID]
export SIGNER_CHAIN_ID=88888
```

**2. Fund your wallet:**

Your signing key needs:
- Input tokens (what you're swapping from)
- Output tokens (what you're providing to users)
- Gas: ETH on Ethereum, USD on Signet

**3. Approve Permit2:**

```bash
cast send [TOKEN_ADDRESS] "approve(address,uint256)" \
  0x000000000022D473030F116dDEE9F6B43aC78BA3 \
  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \
  --rpc-url $RPC_URL
```

Permit2 uses the same address on Parmigiana and Ethereum mainnet.

### Run

**Rollup → Host swap:**
```bash
cargo run --bin order-roundtrip-example
```

**Rollup → Rollup swap:**
```bash
cargo run --bin order-roundtrip-example -- --rollup
```

The example supports both AWS KMS and local private keys.

---

## Production Considerations

When building production systems:

**Profitability analysis**: Calculate spreads accounting for gas costs, inventory costs, and competition.

**Key management**: Use AWS KMS, HashiCorp Vault, or hardware security modules. Never use raw private keys in production.

**Monitoring**: Track fill rates, win rates against competitors, and inventory levels.

**Error handling**: Implement retry logic for network failures. Bundles can target subsequent blocks if the first attempt fails.

**Gas optimization**: Choose aggregate vs individual filling based on your order patterns. High-volume, correlated orders benefit from aggregation.

---

## Integration Patterns

**Cross-chain DeFi**: Let users open positions on Ethereum using Signet collateral—instantly.

**Payment routing**: Route payments to the cheapest chain based on current liquidity.

**Arbitrage**: Capture price differences while providing useful execution to users.

**Wallet interfaces**: Offer "swap to any chain" without users understanding the mechanics.

---

## Resources

**Code:**
- [`signet-orders`](https://github.com/init4tech/signet-orders) — Complete examples
- [`signet-sdk`](https://github.com/init4tech/signet-sdk) — Core types and utilities

**Infrastructure:**
- [Parmigiana Faucet](/docs/build-on-signet/parmigiana/index.md) — Fund your dev keys
- [Parmigiana Explorer](https://explorer.parmigiana.signet.sh/) — Monitor execution

**Concepts:**
- [The Filler Economy](/updates/the-filler-economy/index.md) — How markets work
- [Application Controlled Execution](/updates/application-controlled-execution/index.md) — What apps can do

Questions? [Get in touch](https://t.me/anthspezzano).
