Skip to main content

Overview

WhitelistPreIntentHook is a pre-intent hook that restricts intent signaling to a depositor-managed whitelist of taker addresses. It enables “private orderbook” functionality where deposits are visible on-chain but only whitelisted addresses can lock liquidity. Contract Location: contracts/hooks/WhitelistPreIntentHook.sol Interface: IPreIntentHook Compatible With: OrchestratorV2 (pre-intent hooks only supported in V2)

Use Cases

Private Liquidity Pools

Control access to deposit liquidity:
  • Restrict intents to trusted partners
  • Create private OTC markets
  • Enable institutional-only deposits
  • Prevent public order sniping

Relationship-Based Trading

Depositors can:
  • Whitelist only known counterparties
  • Build trust-based trading networks
  • Enforce business relationships on-chain
  • Create invite-only markets

Risk Management

Limit exposure by:
  • Whitelisting only KYC’d addresses
  • Restricting to verified entities
  • Controlling counterparty risk
  • Preventing unknown takers

Architecture

Per-Deposit Whitelists

Each deposit maintains its own independent whitelist:
This allows:
  • Different whitelists per deposit
  • Fine-grained access control
  • Independent management by different depositors

Authorization Model

Only the deposit owner or delegate can manage the whitelist for their deposit.

Functions

addToWhitelist

Adds one or more taker addresses to the whitelist.
Parameters:
  • _escrow: Escrow contract address
  • _depositId: Deposit ID
  • _takers: Array of taker addresses to whitelist
Authorization: Only deposit owner or delegate Reverts:
  • ZeroAddress(): Escrow or taker address is zero
  • EmptyArray(): Takers array is empty
  • UnauthorizedCallerOrDelegate(): Caller is not owner or delegate
Events:
Example:

removeFromWhitelist

Removes one or more taker addresses from the whitelist.
Parameters:
  • _escrow: Escrow contract address
  • _depositId: Deposit ID
  • _takers: Array of taker addresses to remove
Authorization: Only deposit owner or delegate Reverts:
  • ZeroAddress(): Escrow address is zero
  • EmptyArray(): Takers array is empty
  • UnauthorizedCallerOrDelegate(): Caller is not owner or delegate
  • TakerNotInWhitelist(): Taker was not whitelisted (reverts to prevent mistakes)
Events:
Example:

isWhitelisted

Checks if a taker is whitelisted for a specific deposit.
Returns: true if taker is whitelisted, false otherwise Example:

validateSignalIntent

Validates taker is whitelisted when intent is signaled (called by orchestrator).
Validation:
  1. Verify caller is authorized orchestrator
  2. Check if _ctx.taker is whitelisted for _ctx.escrow and _ctx.depositId
  3. Revert if not whitelisted
Reverts:
  • UnauthorizedOrchestratorCaller(): Caller is not an authorized orchestrator
  • TakerNotWhitelisted(): Taker is not in the whitelist

Usage

Setup: Deploy and Configure

1. Deploy Hook:
2. Configure Deposit to Use Hook: Depositor uses the dedicated whitelist hook slot:
OrchestratorV2 has a dedicated whitelist hook slot separate from the generic pre-intent hook slot. This allows using whitelist functionality without occupying the general-purpose hook slot.
3. Add Takers to Whitelist:

Signal Intent (Taker)

Whitelisted takers can signal intents normally:
If taker is not whitelisted, transaction reverts with TakerNotWhitelisted.

Manage Whitelist (Depositor)

Add Takers:
Remove Takers:
Check Status:

Execution Flow

Events

TakerWhitelisted

Emitted when a taker is added to whitelist:
Emitted once per taker when addToWhitelist is called with multiple addresses.

TakerRemovedFromWhitelist

Emitted when a taker is removed from whitelist:
Emitted once per taker when removeFromWhitelist is called with multiple addresses.

Errors

Error Distinction:
  • TakerNotWhitelisted: Thrown during validateSignalIntent when taker tries to signal
  • TakerNotInWhitelist: Thrown during removeFromWhitelist when trying to remove non-existent entry

Gas Optimization

Batch Operations

Always use batch functions when adding/removing multiple takers: Efficient:
Inefficient:

Storage Costs

Each whitelist entry costs ~20,000 gas (cold SSTORE). For large whitelists:
  • Adding 100 addresses: ~2M gas
  • Adding 1000 addresses: ~20M gas (may hit block gas limit)
Consider alternative approaches for large whitelists:
  • Use SignatureGatingHook for dynamic/large user sets
  • Implement Merkle tree-based whitelist hook for very large sets

Security Considerations

Authorization

Only deposit owner or delegate can modify whitelist:

Orchestrator Validation

Hook verifies caller is authorized orchestrator:

Removal Safety

removeFromWhitelist reverts if taker is not whitelisted. This prevents:
  • Accidental double-removal
  • Typos in removal addresses
  • Unclear whitelist state

Privacy Considerations

Whitelist addresses are public on-chain:
  • Anyone can query isWhitelisted
  • Events reveal all whitelisted addresses
  • Consider SignatureGatingHook for private eligibility criteria

Use Case Examples

Example 1: Private OTC Market

Example 2: KYC-Required Deposits

Example 3: Invite-Based System

Dedicated Whitelist Hook Slot

OrchestratorV2 provides two pre-intent hook slots per deposit:
  1. Generic Pre-Intent Hook: depositPreIntentHooks[escrow][depositId]
    • Set via setDepositPreIntentHook()
    • For general-purpose validation
  2. Dedicated Whitelist Hook: depositWhitelistHooks[escrow][depositId]
    • Set via setDepositWhitelistHook()
    • Specifically for whitelist functionality
    • Allows using whitelist + another hook simultaneously
Both hooks are executed during signalIntent if set:
Example using both:

Comparison with Signature Gating Hook