Documentation Index Fetch the complete documentation index at: https://mintlify.com/rhinestonewtf/warp-router/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Arbiters are specialized contracts that handle settlement validation and resource unlocking for different protocols. They validate user signatures, unlock input tokens, and coordinate target operation execution.
Arbiters are called by adapters to perform the actual settlement logic after pre-funding or other preparation steps are complete.
Arbiter Architecture
ArbiterBase
All arbiters inherit from ArbiterBase, which provides protocol integration:
abstract contract ArbiterBase {
address public immutable ROUTER;
address public immutable COMPACT;
address public immutable EXECUTOR;
address public immutable ADDRESS_BOOK;
modifier onlyRouter () {
require ( msg.sender == ROUTER, OnlyRouter ());
_ ;
}
constructor ( address router , address compact , address addressBook ) {
ROUTER = router;
COMPACT = compact;
ADDRESS_BOOK = addressBook;
EXECUTOR = IAddressBook (addressBook). intentExecutor ();
}
}
Key Components:
Router Access Control Only Router can call arbiter functions via onlyRouter modifier
Protocol Integration Immutable references to Compact, Executor, and AddressBook
Signature Validation Validates user signatures before resource movements
Resource Unlocking Claims user tokens from protocols (Compact, Permit2)
Settlement Flow
Arbiters orchestrate the settlement process in coordination with adapters:
Pre-Funding (Adapter)
Adapter pre-funds recipient with output tokens before calling arbiter
Signature Validation (Arbiter)
Arbiter validates user signatures and order metadata
Pre-Claim Operations (Arbiter)
Execute any required setup operations (approvals, configurations)
Resource Unlock (Arbiter)
Unlock and transfer user’s input tokens to solver
Target Execution (Arbiter)
Execute user-specified operations (swaps, transfers)
SameChainArbiter
Handles same-chain settlements for both Compact and Permit2 protocols:
Compact Settlement
function handleCompact_NotarizedChain (
Types . Order calldata order ,
Types . Signatures calldata sigs ,
bytes32 [] calldata otherElements ,
bytes calldata allocatorData ,
address relayer
) external onlyRouter returns ( address sponsor , uint256 nonce ) {
sponsor = order.sponsor;
nonce = order.nonce;
// Ensure order hasn't expired
require (order.fillDeadline >= block .timestamp, OrderExpired ());
// STEP 1: Pre-claim validation and execution
bytes32 mandateHash = _compactPreClaimOps (
order,
sigs,
otherElements,
0 ,
block .chainid
);
// STEP 2: Resource unlock and deposit to relayer
_unlockNotarizedChain ({
order : order,
otherElements : otherElements,
originChainSig : sigs.notarizedClaimSig,
allocatorData : allocatorData,
depositor : relayer,
mandateHash : mandateHash
});
// STEP 3: Execute target operations
if (order.targetOps.data.length != 0 ) {
address recipient = order.recipient;
SmartExecutionLib.SigMode targetOpsSigMode = order.targetOps. extractSigMode ();
bool sigModeMatch = (
order.preClaimOps.data.length == 0 ||
targetOpsSigMode == order.preClaimOps. extractSigMode ()
);
if (
recipient == sponsor &&
! targetOpsSigMode. isExecutionEmissary () &&
sigModeMatch
) {
EXECUTOR. executeOpsWithoutSignature (recipient, order.targetOps);
}
}
}
STEP 1: Pre-Claim Validation
Validates order signatures and metadata
Executes pre-claim operations (approvals, setup)
Generates mandate hash for resource unlock
Ensures prerequisites before claiming
STEP 2: Resource Unlock
Validates signatures against mandate hash
Unlocks user’s input tokens from Compact
Transfers tokens directly to relayer address
Returns claim hash for tracking
STEP 3: Target Operations
Checks execution conditions (recipient == sponsor, etc.)
Executes user-specified operations without additional signatures
Uses trusted execution pattern for gas efficiency
Maintains atomic execution guarantees
Permit2 Settlement
Streamlined flow for Permit2-based orders:
function handlePermit2 (
Types . Order calldata order ,
Types . Signatures calldata sigs ,
address relayer
) external onlyRouter returns ( address sponsor , uint256 nonce ) {
sponsor = order.sponsor;
nonce = order.nonce;
require (order.fillDeadline >= block .timestamp, OrderExpired ());
// STEP 1: Pre-claim validation (simplified for Permit2)
bytes32 mandateHash = _permit2PreClaimOps (order, sigs);
// STEP 2: Resource unlock via Permit2
_unlockPermit2 ({
order : order,
sig : sigs.notarizedClaimSig,
depositor : relayer,
mandateHash : mandateHash
});
// STEP 3: Execute target operations
if (order.targetOps.data.length != 0 ) {
address recipient = order.recipient;
SmartExecutionLib.SigMode targetOpsSigMode = order.targetOps. extractSigMode ();
bool sigModeMatch = (
order.preClaimOps.data.length == 0 ||
targetOpsSigMode == order.preClaimOps. extractSigMode ()
);
if (
recipient == sponsor &&
! targetOpsSigMode. isExecutionEmissary () &&
sigModeMatch
) {
EXECUTOR. executeOpsWithoutSignature (recipient, order.targetOps);
}
}
}
Permit2 settlement is more gas-efficient than Compact due to simplified validation and unlock process, making it optimal for straightforward token operations.
Trusted Execution Pattern
Arbiters use a trusted execution model for target operations:
Security Model
Execution Conditions
Gas Savings
// SameChainArbiter is whitelisted in IntentExecutor
// This enables executeOpsWithoutSignature after initial validation
EXECUTOR. executeOpsWithoutSignature (
recipient,
order.targetOps
);
Benefits:
Avoids redundant signature validation (already done in pre-claim)
Reduces gas costs significantly
Maintains security through initial validation gate
// Target operations only execute when ALL conditions met:
1 . targetOps.data.length != 0 // Operations specified
2 . recipient == sponsor // Self-execution pattern
3 . ! isExecutionEmissary () // Not delegated execution
4 . sigModeMatch // Signature modes align
// Traditional flow:
// 1. Pre-claim sig validation
// 2. Resource unlock sig validation
// 3. Target ops sig validation ❌ Expensive
// Trusted execution:
// 1. Pre-claim sig validation ✅
// 2. Resource unlock sig validation ✅
// 3. executeOpsWithoutSignature ✅ Gas efficient
Protocol-Specific Validation
Compact Pre-Claim
function _compactPreClaimOps (
Types . Order calldata order ,
Types . Signatures calldata sigs ,
bytes32 [] calldata otherElements ,
uint256 preClaimGasStipend ,
uint256 notarizedChainId
) internal returns ( bytes32 mandateHash ) {
// Validate signatures and metadata
// Execute pre-claim operations with gas stipend
// Generate mandate hash for resource unlock
}
Features:
Complex signature validation
Pre-claim operation execution
Gas stipend allocation
Allocator data handling
Permit2 Pre-Claim
function _permit2PreClaimOps (
Types . Order calldata order ,
Types . Signatures calldata sigs
) internal returns ( bytes32 mandateHash ) {
// Simplified signature validation
// Generate mandate hash
}
Features:
Simplified validation
No pre-claim operations
Lower gas overhead
Resource Unlocking
Compact Unlock
function _unlockNotarizedChain (
Types . Order calldata order ,
bytes32 [] calldata otherElements ,
bytes calldata originChainSig ,
bytes calldata allocatorData ,
address depositor ,
bytes32 mandateHash
) internal returns ( bytes32 claimHash ) {
// Validate against mandate hash
// Unlock tokens from Compact protocol
// Transfer to depositor (relayer)
}
Permit2 Unlock
function _unlockPermit2 (
Types . Order calldata order ,
bytes calldata sig ,
address depositor ,
bytes32 mandateHash
) internal {
// Validate Permit2 signature
// Transfer tokens to depositor
}
Dual Protocol Support
Use Case: Complex multi-step settlementsFeatures:
Pre-claim operations
Gas stipend allocation
Allocator integration
Multi-signature support
Cross-chain coordination
When to Use:
Complex settlement flows
Multi-element orders
Cross-chain operations
Advanced authorization
Use Case: Simple token operationsFeatures:
Simplified validation
Direct token authorization
Lower gas costs
Streamlined flow
When to Use:
Simple token transfers
Basic swaps
Gas-sensitive operations
Single-chain settlements
Security Model
Critical Security Features:
Access Control : Only Router can call arbiter functions
Signature Validation : All user signatures validated before asset movements
Atomic Execution : Entire settlement succeeds or reverts together
Deadline Enforcement : Orders expire after fillDeadline
Trusted Execution : Whitelist-based execution without redundant signatures
Access Control
modifier onlyRouter () {
require ( msg.sender == ROUTER, OnlyRouter ());
_ ;
}
Only the designated Router can call arbiter settlement functions.
Atomicity Guarantees
If any step fails, the entire transaction reverts:
// If signature validation fails → revert (pre-funding also reverted)
// If resource unlock fails → revert
// If target operations fail → revert
Integration Example
How adapters integrate with arbiters:
function _handleCompactFill (
FillDataCompact calldata fillData ,
address tokenInRecipient
) internal {
// 1. Pre-fund recipient (adapter responsibility)
_prefundRecipient ({
from : msg.sender ,
to : fillData.order.recipient,
tokenOut : fillData.order.tokenOut
});
// 2. Call arbiter for settlement (arbiter responsibility)
( address sponsor, uint256 nonce) = SameChainArbiter (ARBITER)
. handleCompact_NotarizedChain ({
order : fillData.order,
sigs : fillData.userSigs,
otherElements : fillData.otherElements,
allocatorData : fillData.allocatorData,
relayer : tokenInRecipient
});
// 3. Emit event (adapter responsibility)
emit RouterFilled (sponsor, nonce);
}
Target Operation Execution
Arbiters coordinate with IntentExecutor for final operations:
if (order.targetOps.data.length != 0 ) {
address recipient = order.recipient;
SmartExecutionLib.SigMode targetOpsSigMode = order.targetOps. extractSigMode ();
bool sigModeMatch = (
order.preClaimOps.data.length == 0 ||
targetOpsSigMode == order.preClaimOps. extractSigMode ()
);
// Only execute if conditions are met
if (
recipient == sponsor && // Self-execution
! targetOpsSigMode. isExecutionEmissary () && // Not delegated
sigModeMatch // Sig modes align
) {
EXECUTOR. executeOpsWithoutSignature (recipient, order.targetOps);
}
}
Execution Conditions:
Target ops exist : targetOps.data.length != 0
Self-execution : recipient == sponsor
Not emissary : !isExecutionEmissary()
Signature mode match : Pre-claim and target ops use same mode
If conditions aren’t met, target operations are skipped (not reverted). This allows for flexible settlement patterns.
Adapters Learn how adapters coordinate with arbiters
Intent Execution Understand intent executor and ERC-7579 integration