Arbiters

Learn how arbiters verify conditions and submit claims for Uniswap The Compact single-chain and multichain compacts.

Arbiters are entities responsible for verifying and submitting claims against resource locks in The Compact protocol. When a sponsor creates a compact, they assign an arbiter per chain. That arbiter is the sole account that can trigger a claim against the compact on the respective chain and determines which accounts receive the locked balances and in what amounts.

Role and Responsibilities

Arbiters serve as intermediaries between sponsors and claimants with these key responsibilities:

ResponsibilityDescription
Claim verificationValidate that claim conditions are met before submission.
Claim submissionSubmit claims to The Compact on behalf of claimants.
Recipient allocationDetermine which accounts receive funds and in what amounts.
Witness data validationVerify witness data included in compacts.
Cross-chain coordinationCoordinate claims across chains for multichain compacts.

Arbiter Selection

Arbiters are specified per compact or per element (in multichain compacts):

Single and batch compacts

struct Compact {
    address arbiter;    // The designated arbiter for this compact
    address sponsor;
    uint256 nonce;
    uint256 expires;
    // ...
}

Multichain compacts

struct Element {
    address arbiter;    // Can be different per chain
    uint256 chainId;
    Lock[] commitments;
    Mandate mandate;    // Required for multichain
}

Specifying Claimants

When submitting a claim, arbiters specify claimants through a Component struct that encodes both the recipient and the destination format:

struct Component {
    uint256 claimant;  // Encodes both lockTag and recipient address
    uint256 amount;    // The amount of tokens to claim
}

Claimant encoding

The claimant field packs two pieces of information:

Encoded valueBitsDescription
bytes12 lockTagUpper 96 bitsDestination format for the claimed resource.
address recipientLower 160 bitsAccount that receives the claimed value.

Destination options

Based on the lockTag in the claimant field, arbiters can direct claimed resources to three different destinations:

1. Direct transfer (keep as ERC6909)

When the lockTag matches the original resource lock's tag, the ERC6909 tokens are transferred directly to the recipient. This maintains the same lock properties (allocator, reset period, scope).

2. Convert to new resource lock

When the lockTag is non-zero but different from the original, the tokens are converted to a new resource lock with different properties. This allows changing allocators, reset periods, or scopes while keeping funds locked.

3. Withdraw to underlying token

When the lockTag is bytes12(0), the ERC6909 tokens are burned and the underlying tokens (native or ERC20) are withdrawn to the recipient. This fully exits The Compact system.

To prevent griefing attacks (e.g., via malicious receive hooks or intentionally underpaying gas), The Compact implements a withdrawal fallback mechanism:

  1. The protocol first attempts withdrawals with half the available gas
  2. If this fails (and sufficient gas remains above a benchmarked stipend), it falls back to a direct ERC6909 transfer to the recipient

This mechanism ensures that claims cannot be maliciously blocked through receive hook manipulation, while still preserving the intended withdrawal functionality under normal conditions.

The required gas stipends for this fallback are determined through benchmarking, which measures:

  • Cold account access costs
  • Typical ERC20 transfer gas requirements
  • Native token transfer gas requirements

The benchmark can be re-run at any time through a call to __benchmark.

Example

// Example: Arbiter specifying three different destinations
Component[] memory claimants = new Component[](3);

// Direct transfer - keep same lock properties
claimants[0] = Component({
    claimant: uint256(uint160(alice)) | (uint256(originalLockTag) << 160),
    amount: 100e18
});

// Convert to new lock with different allocator
claimants[1] = Component({
    claimant: uint256(uint160(bob)) | (uint256(newLockTag) << 160),
    amount: 50e18
});

// Withdraw to underlying token
claimants[2] = Component({
    claimant: uint256(uint160(charlie)), // lockTag is 0
    amount: 25e18
});

Submitting Claims

Arbiters submit claims using one of six available claim functions based on:

DimensionOptionsMeaning
Lock scopeSingle / BatchClaim against one resource lock or multiple locks on a chain.
Chain scopeSingle-chain / MultichainClaim against one chain or a compact spanning multiple chains.
Multichain pathNotarized / ExogenousClaim on the primary signed chain or on non-notarized chains.

Single-chain claims

claim (Compact)

For single resource lock on a single chain:

function claim(Claim calldata claimPayload) external returns (bytes32 claimHash)

batchClaim (BatchCompact)

For multiple resource locks on a single chain:

function batchClaim(BatchClaim calldata claimPayload) external returns (bytes32 claimHash)

Multichain claims

multichainClaim (MultichainCompact - Notarized)

For single resource lock on the notarized chain (domain matches signature):

function multichainClaim(
    MultichainClaim calldata claimPayload
) external returns (bytes32 claimHash)

exogenousClaim (MultichainCompact - Exogenous)

For single resource lock on exogenous chains (not the notarized chain):

function exogenousClaim(
    ExogenousMultichainClaim calldata claimPayload
) external returns (bytes32 claimHash)

batchMultichainClaim (BatchMultichainClaim - Notarized)

For multiple resource locks on the notarized chain:

function batchMultichainClaim(
    BatchMultichainClaim calldata claimPayload
) external returns (bytes32 claimHash)

exogenousBatchClaim (BatchMultichainClaim - Exogenous)

For multiple resource locks on exogenous chains:

function exogenousBatchClaim(
    ExogenousBatchMultichainClaim calldata claimPayload
) external returns (bytes32 claimHash)

Trust Model

For sponsors

Sponsors trust arbiters to:

ExpectationWhy it matters
Submit only valid claimsPrevents unauthorized or premature resource movement.
Avoid collusion with claimantsReduces risk of malicious lock draining.
Verify witness data correctlyPreserves compact conditions and sponsor intent.

For claimants

Claimants trust arbiters to:

ExpectationWhy it matters
Submit claims promptlyAvoids unnecessary settlement delays.
Avoid censoring valid claimsEnsures fair claim execution.
Distribute resources per compact termsPreserves expected payout behavior.

Arbiter Authorization

When an arbiter submits a claim, The Compact verifies authorization in this order:

  1. Arbiter is Caller: The msg.sender must match the arbiter specified in the compact
  2. Claim Validity: The claim must be valid (not expired, correct nonce, etc.)
  3. Sponsor Signature: The sponsor's signature must authorize the compact (unless registered)
  4. Allocator Authorization: The allocator must approve the claim

Best Practices

For arbiter selection

PracticeBenefit
Choose arbiters with proven track recordsImproves baseline reliability.
Consider decentralized arbiter networksReduces dependence on a single trusted actor.
Implement arbiter reputation systemsIncreases accountability over time.

For arbiter implementation

PracticeBenefit
Validate all claim parameters before submissionCatches malformed claims before onchain execution.
Implement robust witness data verificationPreserves integrity of witness-bound conditions.
Maintain audit logs of claim submissionsImproves traceability and incident response.
Use secure key management for arbiter accountsReduces operational compromise risk.

Common Patterns

Automated arbiters

Smart contracts can act as arbiters to provide trustless claim verification:

PatternDescription
Oracle-based arbitersVerify external conditions via oracle inputs.
Time-locked arbitersEnforce release schedules through timelocks.
Multi-signature arbitersRequire multiple approvals before claim submission.

Arbiter networks

Multiple arbiters can be coordinated through:

PatternDescription
Consensus-based approvalRequires network-level agreement before claim execution.
Reputation-based selectionWeights arbiter participation by historical behavior.
Stake-based securityUses economic stake to discourage malicious behavior.

Error Handling

Common arbiter-related errors:

ErrorMeaning
InvalidArbiter()Caller is not the designated arbiter.
ClaimExpired()Claim has passed its expiration time.
InvalidClaimSignature()Sponsor signature is invalid.
UnauthorizedClaim()Arbiter is not authorized for this claim.

Events

Key events related to arbiter actions:

event Claim(
    address indexed sponsor,
    address indexed allocator,
    address indexed arbiter,
    bytes32 claimHash,
    uint256 nonce
)

Security Considerations

Arbiter compromise

Risk or mitigationDetails
Key compromise riskA compromised arbiter key may submit unauthorized claims.
Activity monitoringSponsors should monitor suspicious claim activity.
Defense-in-depth controlsUse timelocks or multisig requirements for high-value compacts.

Arbiter censorship

Risk or mitigationDetails
Censorship riskArbiters could refuse to submit valid claims.
Multiple arbitersReduces reliance on a single operator.
Replacement mechanismsAllows rotating away from unresponsive arbiters.
Expiration designAppropriate expirations reduce prolonged lockups.

Front-running protection

PracticeBenefit
Use private mempools or commit-reveal schemesReduces public mempool extraction risk.
Use Flashbots bundles for sensitive claimsImproves inclusion control for high-sensitivity claims.