TESTNET ONLINE: PECORINO PECORINO

Working with Orders

Conditional transactions via Signed Orders

Signet orders use the Permit2 standard, allowing users to authorize token transfers with a single signature. This intent mechanism powers Signet’s swaps, allowing users to express intents like:

“I want to swap 5 Signet ETH for 1000 USDC on Ethereum”

Nothing happens if the exact conditions you specify are not met.

Technical Order Structure

 1// Wrapper with order ID
 2pub struct Order {
 3    /// The order id. This is the signature of the order.
 4    pub id: String,
 5    /// The order.
 6    pub order: SignedOrder,
 7}
 8
 9// Core signed order structure
10pub struct SignedOrder {
11    /// The permit batch.
12    #[serde(flatten)]
13    pub permit: Permit2Batch,
14    /// The desired outputs.
15    pub outputs: Vec<o>,
16}
17
18// Output definition
19pub struct Output {
20    pub token: Address,
21    pub amount: Uint<256, 4>,
22    pub recipient: Address,
23    pub chainId: u32,
24}

Permit2 Batches

1// Permit2 batches
2pub struct Permit2Batch {
3    pub permit: PermitBatchTransferFrom,
4    pub owner: Address,
5    pub signature: Bytes,
6}

Permit2 batches contain individually signed transactions, allowing multiple inputs (what the user provides) to map to desired outputs (what the user receives).

For Users: Working with Orders

Users interact with Signet’s order system primarily when moving assets from Signet to Ethereum.

Creating a Signed Order

To create a Signed Order, follow these steps:

  1. Decide which assets you’re willing to provide (inputs) and what you want to receive (outputs)
  2. Authorize the Permit2 contract to manage your tokens
  3. Sign the order with your wallet
  4. Submit the order to the orders cache
 1{
 2  // Inputs (what you're providing)
 3  "inputs": [
 4    {
 5      "token": "0x...", // Address of token on Signet
 6      "amount": "1000000000000000000" // 1 ETH in wei
 7    }
 8  ],
 9  // Outputs (what you want to receive)
10  "outputs": [
11    {
12      "token": "0x...", // Address of USDC on Ethereum
13      "amount": "1000000000", // 1000 USDC with 6 decimals
14      "recipient": "0x...", // Your Ethereum address
15      "chainId": 1 // Ethereum mainnet
16    }
17  ]
18}

Order Status

You can check the status of your orders:

  • Pending: Order is in the cache waiting to be filled
  • Filled: Order has been successfully executed
  • Expired: Order has passed its deadline without being filled

User Best Practices

  • Set reasonable price expectations for cross-chain swaps
  • Monitor orders that remain unfilled for extended periods
  • Consider setting a deadline to ensure stale orders don’t execute at unfavorable rates

Order Signing Implementation

Using the Signet SDK

The Signet SDK provides utilities to simplify order creation and signing. Here’s how to create and sign orders programmatically:

Complete Order Signing Workflow

 1use signet_types::signing::order::{UnsignedOrder, SignedOrder};
 2use signet_zenith::RollupOrders::{Order, Output};
 3use alloy::signers::Signer;
 4
 5// 1. Create an Order with inputs and outputs
 6let order = Order {
 7    inputs: vec![/* your input tokens */],
 8    outputs: vec![
 9        Output {
10            token: usdc_address,
11            amount: 1000_000_000_u64.into(), // 1000 USDC
12            recipient: user_address,
13            chainId: 1, // Ethereum mainnet
14        }
15    ],
16    deadline: current_timestamp + 3600, // 1 hour from now
17};
18
19// 2. Create an UnsignedOrder with chain configuration
20let unsigned_order = UnsignedOrder::from(&order)
21    .with_chain(signet_chain_id, signet_order_contract_address)
22    .with_nonce(permit2_nonce); // Optional: will use timestamp if not provided
23
24// 3. Sign the order
25let signed_order = unsigned_order.sign(&signer).await?;
26
27// 4. Generate transaction to initiate the order
28let initiate_tx = signed_order.to_initiate_tx(
29    filler_token_recipient,
30    order_contract_address
31);

Source: Implementation example inspired by SDK types from signet-sdk/crates/types/src/signing/order.rs and signet-zenith

Key Components Explained

UnsignedOrder Helper: The SDK provides an UnsignedOrder type that handles Permit2 encoding and signature generation. It’s a builder pattern that lets you configure chain IDs, nonces, and other parameters before signing.

Automatic Permit2 Handling: The SDK automatically generates the correct Permit2 batch structure, including:

  • Token permissions for each input
  • Deadline management
  • Nonce generation (defaults to current timestamp in microseconds)
  • Proper EIP-712 signature formatting

Transaction Generation: The to_initiate_tx method creates a properly formatted transaction that can be submitted to initiate the order on the rollup.

Validation and Error Handling

 1// Validate a signed order before submission
 2match signed_order.validate(current_timestamp) {
 3    Ok(()) => {
 4        // Order is valid, proceed with submission
 5        println!("Order is valid");
 6    }
 7    Err(SignedPermitError::DeadlinePassed { current, deadline }) => {
 8        println!("Order deadline has passed: {} > {}", current, deadline);
 9    }
10    Err(e) => {
11        println!("Order validation failed: {:?}", e);
12    }
13}

Source: Exact API usage from signet-sdk/crates/types/src/signing/mod.rs

Best Practices

Important Guidelines:
  • Private Keys: Never expose private keys in client-side code. Use secure key management.
  • Deadline Management: Always set reasonable deadlines to prevent stale orders from executing at unfavorable rates.
  • Nonce Handling: If providing custom nonces, ensure they’re unique to prevent replay attacks.
  • Amount Validation: Double-check token amounts and decimal places before signing.

Common Patterns

Setting Custom Deadlines:

1let unsigned_order = UnsignedOrder::from(&order)
2    .with_chain(chain_id, contract_address)
3    .with_nonce(custom_nonce); // Use specific nonce for order management

Source: Implementation pattern using signet-sdk types

**Batch Order Creation:

1// For creating multiple orders efficiently
2for order in orders {
3    let signed_order = UnsignedOrder::from(&order)
4        .with_chain(chain_id, contract_address)
5        .sign(&signer).await?;
6    
7    submit_order(signed_order).await?;
8}

Source: Implementation pattern using signet-sdk types