Skip to main content

Overview

The EscrowRegistry is a registry contract that manages a whitelist of authorized escrow contracts. It provides a flexible system that can either operate in whitelist mode (only specific escrows allowed) or in permissionless mode (all escrows accepted). Contract Location: contracts/registries/EscrowRegistry.sol

Purpose

The EscrowRegistry serves several important functions:
  • Escrow Whitelisting: Maintain a list of trusted escrow contracts
  • Flexible Mode: Support both whitelisted and permissionless operation modes
  • Access Control: Prevent unauthorized escrow contracts from being used
  • Governance: Enable protocol owners to control which escrows are trusted

State Variables

bool public acceptAllEscrows;
mapping(address => bool) public isWhitelistedEscrow;
address[] public escrows;
  • acceptAllEscrows: When true, all escrows are accepted; when false, only whitelisted escrows
  • isWhitelistedEscrow: Maps escrow addresses to their whitelist status
  • escrows: Array of all whitelisted escrow addresses

Core Functions

Adding Escrows

function addEscrow(address _escrow) external onlyOwner
Adds an escrow contract to the whitelist. Parameters:
  • _escrow: Address of the escrow contract to whitelist
Requirements:
  • Escrow address cannot be zero address
  • Escrow must not already be whitelisted
  • Only callable by owner
Emits: EscrowAdded(address indexed escrow) Reference: contracts/registries/EscrowRegistry.sol:33

Removing Escrows

function removeEscrow(address _escrow) external onlyOwner
Removes an escrow contract from the whitelist. Parameters:
  • _escrow: Address of the escrow contract to remove
Requirements:
  • Escrow must be currently whitelisted
  • Only callable by owner
Emits: EscrowRemoved(address indexed escrow) Reference: contracts/registries/EscrowRegistry.sol:48

Setting Permissionless Mode

function setAcceptAllEscrows(bool _acceptAll) external onlyOwner
Configures whether all escrows are accepted or only whitelisted ones. Parameters:
  • _acceptAll: True to accept all escrows, false to require whitelisting
Use Cases:
  • true: Permissionless mode - any escrow can be used (less restrictive)
  • false: Whitelist mode - only explicitly added escrows can be used (more secure)
Emits: AcceptAllEscrowsUpdated(bool acceptAll) Reference: contracts/registries/EscrowRegistry.sol:62

View Functions

Check Acceptance Status

function isAcceptingAllEscrows() external view returns (bool)
Returns whether the registry is in permissionless mode. Reference: contracts/registries/EscrowRegistry.sol:70

Get Whitelisted Escrows

function getWhitelistedEscrows() external view returns (address[] memory)
Returns array of all whitelisted escrow addresses. Reference: contracts/registries/EscrowRegistry.sol:74

Check Escrow Status

The isWhitelistedEscrow mapping is public, allowing anyone to check if a specific escrow is whitelisted:
bool isWhitelisted = escrowRegistry.isWhitelistedEscrow(escrowAddress);

Integration with Core Contracts

Orchestrator

The Orchestrator contracts (Orchestrator.sol and OrchestratorV2.sol) use the EscrowRegistry to validate escrow contracts:
// In Orchestrator constructor
escrowRegistry = IEscrowRegistry(_escrowRegistry);

// Validation logic (conceptual)
require(
    escrowRegistry.acceptAllEscrows || escrowRegistry.isWhitelistedEscrow(escrowAddress),
    "Escrow not authorized"
);
Reference: contracts/Orchestrator.sol:82

RateManagerV1

The RateManagerV1 also references the EscrowRegistry to ensure it only interacts with authorized escrows. Reference: contracts/RateManagerV1.sol:126

Configuration Updates

Orchestrator contracts can update their escrow registry reference:
function setEscrowRegistry(address _escrowRegistry) external onlyOwner {
    escrowRegistry = IEscrowRegistry(_escrowRegistry);
    emit EscrowRegistryUpdated(_escrowRegistry);
}
Reference: contracts/Orchestrator.sol:279

Access Control

Owner-Only Functions

All state-modifying functions require owner privileges:
  • addEscrow(): Add escrow to whitelist
  • removeEscrow(): Remove escrow from whitelist
  • setAcceptAllEscrows(): Configure permissionless mode
Access Control Pattern: OpenZeppelin’s Ownable with onlyOwner modifier

View Functions

All query functions are publicly accessible:
  • isAcceptingAllEscrows()
  • getWhitelistedEscrows()
  • isWhitelistedEscrow[address] (public mapping)

Events

event EscrowAdded(address indexed escrow);
event EscrowRemoved(address indexed escrow);
event AcceptAllEscrowsUpdated(bool acceptAll);
These events enable:
  • Monitoring escrow whitelist changes
  • Tracking mode switches between whitelist and permissionless
  • Off-chain indexing of authorized escrows

Usage Patterns

// Set to whitelist mode
escrowRegistry.setAcceptAllEscrows(false);

// Add trusted escrows
escrowRegistry.addEscrow(escrowV2Address);
escrowRegistry.addEscrow(testEscrowAddress);

// Validation in consuming contract
function validateEscrow(address _escrow) internal view {
    require(
        escrowRegistry.acceptAllEscrows || escrowRegistry.isWhitelistedEscrow(_escrow),
        "Unauthorized escrow"
    );
}

Permissionless Mode (Testing/Development)

// Allow all escrows
escrowRegistry.setAcceptAllEscrows(true);

// Any escrow address will be accepted

Security Considerations

Whitelist Mode Security

  1. Explicit Trust: Only explicitly approved escrows can be used
  2. Owner Control: Centralized governance over escrow approval
  3. Audit Trail: Events track all whitelist changes

Permissionless Mode Risks

  1. No Validation: Any contract can act as an escrow
  2. Malicious Escrows: Unaudited escrows could be exploited
  3. User Risk: Users must verify escrow trustworthiness themselves
Recommendation: Use whitelist mode (acceptAllEscrows = false) in production

Upgrade Safety

  • Removing an escrow doesn’t affect existing deposits in that escrow
  • Adding an escrow doesn’t automatically make it trusted by users
  • Mode changes are immediate and affect all subsequent validations

Deployment Strategy

  1. Initial Deployment: Deploy with acceptAllEscrows = false (secure default)
  2. Add Escrows: Whitelist production escrow contracts
  3. Configure Orchestrator: Set registry address in Orchestrator
  4. Monitor Events: Track whitelist changes via events

Build docs developers (and LLMs) love