TESTNET ONLINE: PECORINO PECORINO

Market Participants

Our market-based approach eliminates the need for verification periods or complex bridging. Users move assets instantly between chains.

Searchers

Searchers connect orders with liquidity and are essential for creating efficient markets by:

  • Scanning orders cache
  • Building matching permits into bundles
  • Submitting these bundles to block builders
  • Driving efficiency by connecting orders with liquidity
Finding Opportunities

To operate as a Searcher:

  1. Connect to the orders cache to receive updates about new orders
  2. Implement efficient filtering to identify profitable opportunities
  3. Use the order aggregation functionality to organize multiple orders
1// Example order aggregation
2pub struct AggregateOrders {
3    // Outputs to be transferred to users
4    pub outputs: HashMap<(u64, Address), HashMap<Address, U256>>,
5    // Inputs to be transferred to the filler
6    pub inputs: HashMap<Address, U256>,
7}

Creating Bundles

When building bundles that include orders:

  1. Collect compatible orders that can be matched together
  2. Ensure atomic execution across chains
  3. Include necessary host fills for cross-chain actions
  4. Submit the bundle to the bundle cache

Fillers

Fillers provide liquidity to the system by:

  • Fulfilling open orders with their own assets
  • Enabling cross-chain transfers without traditional bridges
  • Making instant withdrawals possible
Becoming a Filler

To operate as a Filler:

  1. Maintain sufficient liquidity on both Signet and Ethereum
  2. Monitor the orders cache for opportunities
  3. Create corresponding transactions to fulfill orders
  4. Submit fulfillment transactions through bundles

Filling Cross-Chain Orders

When fulfilling a cross-chain order:

  1. Verify the user’s input assets on Signet
  2. Prepare corresponding assets on Ethereum
  3. Submit a bundle with the necessary host fills
  4. Collect the user’s assets once the order executes

Fill Signing Implementation

Creating and Signing Fills

Fillers must create SignedFill transactions to provide the outputs requested by orders. The Signet SDK provides utilities to handle the complex Permit2 signing process:

Complete Fill Signing Workflow

 1use signet_types::signing::fill::{UnsignedFill, SignedFill};
 2use signet_types::agg::AggregateOrders;
 3use alloy::signers::Signer;
 4use std::collections::HashMap;
 5
 6// 1. Aggregate compatible orders
 7let aggregate_orders = AggregateOrders {
 8    outputs: order_outputs, // What users want to receive
 9    inputs: order_inputs,   // What fillers will receive
10};
11
12// 2. Create UnsignedFill for multiple target chains
13let unsigned_fill = UnsignedFill::new(&aggregate_orders)
14    .with_rv_chain_id(signet_chain_id) // Rollup chain where orders originated
15    .with_chain(ethereum_chain_id, ethereum_order_contract) // Ethereum
16    .with_chain(base_chain_id, base_order_contract)         // Base L2
17    .with_deadline(current_timestamp + 600)  // 10 minutes
18    .with_nonce(custom_nonce);               // Optional
19
20// 3. Sign fills for all target chains
21let signed_fills: HashMap<u64, SignedFill> = unsigned_fill.sign(&signer).await?;
22
23// 4. Generate transactions for each chain
24for (chain_id, signed_fill) in signed_fills {
25    let fill_tx = signed_fill.to_fill_tx(order_contracts[&chain_id]);
26    submit_transaction(chain_id, fill_tx).await?;
27}

Source: Implementation example inspired by signet-sdk/crates/types/src/signing/fill.rs

Single Chain Fill Example

For simpler use cases filling orders on a single chain:

1// Fill orders only on Ethereum
2let unsigned_fill = UnsignedFill::new(&aggregate_orders)
3    .with_rv_chain_id(signet_chain_id)
4    .with_chain(ethereum_chain_id, ethereum_order_contract)
5    .with_deadline(current_timestamp + 300); // 5 minutes
6
7let signed_fill = unsigned_fill.sign_for(ethereum_chain_id, &signer).await?;
8let fill_tx = signed_fill.to_fill_tx(ethereum_order_contract);

Source: Implementation example inspired by signet-sdk/crates/types/src/signing/fill.rs

Fill Validation and Security

 1// Validate fills before submission
 2match signed_fill.validate(current_timestamp) {
 3    Ok(()) => {
 4        println!("Fill is valid, proceeding with submission");
 5    }
 6    Err(SignedPermitError::DeadlinePassed { current, deadline }) => {
 7        println!("Fill deadline has passed: {} > {}", current, deadline);
 8        return Err("Fill expired".into());
 9    }
10    Err(SignedPermitError::PermitMismatch) => {
11        println!("Permit tokens/amounts don't match outputs");
12        return Err("Invalid fill structure".into());
13    }
14    Err(e) => {
15        println!("Fill validation error: {:?}", e);
16        return Err(e.into());
17    }
18}

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

Important Best Practices for Fills:
  • Keep SignedFills Private: A SignedFill should remain private until it is mined. There is no guarantee that desired Order Inputs will be received in return for the Outputs offered by the signed Permit2Batch.

  • Use Private Transaction Relays: Use private transaction relays to send bundles containing SignedFills to builders. Public mempools expose fills to potential front-running.

  • Atomic Submission: SignedFills should be submitted atomically with the corresponding SignedOrder(s) to claim the inputs. Avoid submitting a fill without the matching orders.

  • Trusted Endpoints: Bundles can be sent to a trusted Signet Node’s signet_sendBundle endpoint for processing.

Advanced Fill Patterns

Multi-Chain Fill Coordination:

 1// Ensure all target chains are filled atomically
 2let mut transactions = HashMap::new();
 3
 4for (chain_id, signed_fill) in signed_fills {
 5    let tx = signed_fill.to_fill_tx(order_contracts[&chain_id]);
 6    transactions.insert(chain_id, tx);
 7}
 8
 9// Submit all transactions in a coordinated bundle
10submit_cross_chain_bundle(transactions).await?;

Source: Implementation pattern using signet-sdk types

**Fill Profitability Calculation:

1// Calculate expected profit before signing fills
2let input_value = calculate_token_value(&aggregate_orders.inputs);
3let output_value = calculate_token_value(&aggregate_orders.outputs);
4let gas_costs = estimate_gas_costs(&signed_fills);
5
6let expected_profit = input_value - output_value - gas_costs;
7if expected_profit <= minimum_profit_threshold {
8    return Err("Insufficient profit margin".into());
9}

Source: Custom implementation example for filler profitability calculations

Error Recovery

If a fill fails, fillers need to handle various scenarios:

 1match fill_result {
 2    Ok(receipt) => {
 3        println!("Fill successful: {:?}", receipt.transaction_hash);
 4    }
 5    Err(FillError::InsufficientBalance) => {
 6        // Filler doesn't have enough tokens
 7        println!("Need to top up token balance");
 8    }
 9    Err(FillError::OrderAlreadyFilled) => {
10        // Another filler got there first
11        println!("Order was filled by another participant");
12    }
13    Err(FillError::SlippageExceeded) => {
14        // Price moved unfavorably
15        println!("Order no longer profitable");
16    }
17}

Source: Custom implementation example for fill error handling

Orders API Reference

Order Cache

The Order Cache provides endpoints for submitting and retrieving orders:

  • GET /orders: Retrieve all active orders in the cache
  • GET /orders/{id}: Get a specific order by ID
  • POST /orders: Submit a new order to the cache
  • DELETE /orders/{id}: Cancel an order (requires signature)

Order Simulation

Before submitting orders or bundles, you can simulate their execution:

 1// Example simulation request
 2{
 3  "jsonrpc": "2.0",
 4  "id": 1,
 5  "method": "signet_simBundle",
 6  "params": [{
 7    "txs": ["0x..."], // Array of signed transactions
 8    "blockNumber": "0x...", // Target block number
 9    "host_fills": {
10      // Host fills specification
11    }
12  }]
13}

Error Handling

Common errors when working with orders:

Error CodeDescriptionResolution
1001Invalid signatureVerify signing process
1002Insufficient balanceEnsure adequate token balance
1003Expired orderCheck order deadline
1004Price slippageAdjust price expectations