Solidity Orders
Build smart contracts that create, fill, or interact with Signet Orders. These examples demonstrate practical patterns for capturing MEV, automating exits, and creating novel cross-chain primitives.
Quick Start
Clone the examples repository:
1git clone https://github.com/init4tech/signet-sol
2cd signet-sol
3forge build
4forge test
Example Contracts
All examples use the Signet Orders system to enable cross-chain, instant, atomic, and composable operations.
SignetStd.sol - System Configuration
Auto-configure Signet system parameters based on chain ID. Use this as a base for contracts that need to interact with Signet.
When to use:
- You’re building a contract that creates or interacts with Orders
- You need to reference Signet system contracts
- You want chain-agnostic Signet integration
1import {SignetStd} from "./SignetStd.sol";
2
3contract YourContract is SignetStd {
4 function createOrder() external {
5 // Automatically has access to:
6 // - rollupOrders: The Orders contract address
7 // - permit2: The Permit2 contract address
8 // - Other Signet system parameters
9 }
10}
Flash.sol - Cross-Chain Flash Loans
Flash borrow any asset by using an Order where the Output becomes the Input to its own Order.
When to use:
- You need temporary liquidity for a transaction
- You want to perform cross-chain arbitrage
- You need to borrow assets without upfront collateral
How it works:
- Request a flash loan of X tokens
- Searchers provide the tokens (knowing they’ll be repaid)
- Your contract executes logic with the borrowed assets
- The Order output repays the input, completing the cycle
1// Example: Flash borrow WETH for arbitrage
2flashBorrow(wethAddress, amount, arbitrageCalldata);
Source: Flash.sol
GetOut.sol - Quick Exit with Fee
Exit Signet by offering searchers a 50 basis point fee. The simplest way to move assets from Signet to Ethereum.
When to use:
- You want a one-line function to exit Signet
- You’re willing to pay a small fee for immediate exit
- You’re building a UI that needs a simple exit mechanism
1// Exit Signet with a 50bps fee
2getOut(tokenAddress, amount, recipient);
What happens:
- Your contract locks tokens on Signet
- Creates an Order offering 99.5% of tokens on Ethereum
- Searchers fill the order for the 0.5% profit
- You receive tokens on Ethereum instantly
Source: GetOut.sol
PayMe.sol - Payment Gating
Gate contract execution behind a payment using an Order with no inputs. The calling contract doesn’t need to manage cash flow–any third party can fill the payment order.
When to use:
- You want users to pay for contract execution
- You don’t want your contract to handle payment logic
- You want to allow third-party payment (gasless transactions)
How it works:
- Your contract creates an Order with only outputs (payment required)
- Contract execution is invalid unless someone fills the Order
- Unlike
msg.value
checks, the payer can be anyone - Greatly simplifies payment logic
1function executeWithPayment() external {
2 // Create payment order
3 payMe(usdcAddress, 10e6); // Require 10 USDC payment
4
5 // Your contract logic here
6 // Only executes if payment Order is filled
7}
Source: PayMe.sol
PayYou.sol - MEV Capture & Bounties
Generate MEV by offering an Order with no outputs. This creates a bounty for calling your contract, functioning as an incentivized scheduling system.
When to use:
- You want to incentivize someone to call your contract
- You’re creating an automated system that needs execution
- You want to capture MEV produced by your protocol
How it works:
- Your contract creates an Order with only inputs (no outputs required)
- Searchers compete to call your contract to claim the bounty
- Functions as an incentivized scheduling/execution system
1function executeAndPay() external {
2 // Your contract logic that generates value
3 performArbitrage();
4
5 // Pay searchers for executing
6 payYou(wethAddress, 0.01 ether); // Offer 0.01 ETH bounty
7}
Use cases:
- Liquidation systems
- Automated rebalancing
- Scheduled maintenance
- MEV extraction from your protocol
Source: PayYou.sol
Building Your Own
Use these patterns as building blocks:
- Inherit SignetStd for automatic configuration
- Combine patterns (e.g., PayMe + PayYou for payment flows)
- Test thoroughly with
forge test
- Deploy to Signet testnet first
Testing
Run the test suite:
1forge test
2forge test -vvv # Verbose output
Format your code:
1forge fmt
Best Practices
Approve Permit2
Before your contract can create Orders, approve Permit2:
1IERC20(token).approve(permit2Address, type(uint256).max);
Handle Order Failures
Orders can fail if no Filler accepts them. Build fallback logic:
1if (!orderFilled) {
2 // Fallback logic
3 revert("Order not filled");
4}
Set Reasonable Outputs
Make sure output amounts are attractive to Fillers:
- Too greedy: No one will fill your order
- Too generous: You lose value unnecessarily
- Just right: Quick fills at fair prices
Gas Optimization
Orders add gas costs. Optimize by:
- Batching multiple orders when possible
- Using appropriate deadlines
- Minimizing output complexity
Next Steps
- Clone the signet-sol repository
- Read through the example contracts
- Modify an example to fit your use case
- Test on Pecorino testnet
- Deploy to production
For programmatic order creation and filling, check out Rust Orders.