Skip to main content

Contract Overview

ContractTypePurpose
EscrowFactoryUpgradeable (UUPS)Creates and tracks escrows
AgentRegistryUpgradeable (UUPS)Manages agent lifecycle
FeeManagerUpgradeable (UUPS)Fee configuration
EscrowImplementationImmutableTemplate for escrow clones

EscrowFactory

Storage

address public implementation;
address public agentRegistry;
address public feeManager;
address public treasury;
mapping(address => bool) public isEscrow;

Key Functions

createEscrow

Creates and funds a new escrow atomically.
function createEscrow(
    bytes32 userSalt,
    address seller,
    address agent,           // address(0) for locked
    address token,
    uint256 amount,
    uint256 buyerProtectionTime,
    bytes32 termsHash,
    uint256 version,
    address expectedEscrow   // Safety check
) external returns (address escrow);
Flow:
  1. Calculate salt: keccak256(userSalt, msg.sender)
  2. Predict escrow address via CREATE2
  3. Validate: token whitelisted, amount valid, agent valid
  4. Transfer protocol fee to treasury
  5. Transfer escrow amount to predicted address
  6. Deploy clone
  7. Initialize escrow
  8. Set isEscrow[escrow] = true

quoteCreateEscrow

Preview an escrow creation without executing.
function quoteCreateEscrow(
    bytes32 userSalt,
    address seller,
    address agent,
    address token,
    uint256 amount,
    uint256 buyerProtectionTime
) external view returns (
    address predictedAddress,
    uint256 creationFee,
    uint256 assignmentFee
);

AgentRegistry

Storage

struct Agent {
    bool registered;
    bool available;
    uint256 stablecoinStake;
    uint256 tokenStake;
    uint256 assignmentFeeBps;
    uint256 disputeFeeBps;
    uint256 activeCases;
    uint256 lastCaseTimestamp;
}
mapping(address => Agent) public agents;

Key Functions

register

function register(
    uint256 stablecoinAmount,
    uint256 tokenAmount,
    uint256 assignmentFeeBps,
    uint256 disputeFeeBps
) external;

addStake / withdrawStake

function addStake(uint256 stablecoinAmount, uint256 tokenAmount) external;
function withdrawStake(uint256 stablecoinAmount, uint256 tokenAmount) external;

validateAgentForContract

function validateAgentForContract(
    address agent,
    uint256 contractValueWad  // 18-decimal normalized
) external view returns (bool);
Checks:
  • Agent is registered
  • Agent is available
  • Agent’s MAV ≥ contract value
  • Agent has minimum stakes

FeeManager

Storage

struct TokenConfig {
    bool whitelisted;
    uint8 decimals;
    uint256 creationFeeBps;
    uint256 minCreationFee;
    uint256 maxCreationFee;
}
mapping(address => TokenConfig) public tokenConfigs;

Key Functions

quoteCreationFee

function quoteCreationFee(
    address token,
    uint256 amount
) external view returns (uint256 fee);
Logic:
rawFee = amount * feeBps / 10000
fee = clamp(rawFee, minFee, maxFee)

EscrowImplementation

Storage

// Core parties
address public buyer;
address public seller;
address public agent;

// Funds
address public token;
uint256 public amount;

// Time parameters
uint256 public buyerProtectionTime;
uint256 public sellerAcceptDeadline;
uint256 public fulfilledAt;

// State
EscrowState public state;
bytes32 public termsHash;

// Split negotiation
uint256 public proposedBuyerBps;
uint256 public proposedSellerBps;
address public splitProposer;

State Enum

enum EscrowState {
    PENDING,        // 0
    ACTIVE,         // 1
    FULFILLED,      // 2
    RELEASED,       // 3 (terminal)
    REFUNDED,       // 4 (terminal)
    DISPUTED,       // 5
    AGENT_INVITED,  // 6
    SPLIT,          // 7 (terminal)
    AGENT_RESOLVED  // 8 (terminal)
}

Key Functions

accept / decline

function accept() external;  // Seller only, PENDING -> ACTIVE
function decline() external; // Seller only, PENDING -> REFUNDED

markFulfilled

function markFulfilled() external; // Seller only, ACTIVE -> FULFILLED

release

function release() external; // Buyer only, -> RELEASED

sellerRefund

function sellerRefund() external; // Seller only, -> REFUNDED

openDispute

function openDispute() external; // Buyer only, -> DISPUTED

inviteAgent

function inviteAgent() external; // Either party, DISPUTED -> AGENT_INVITED

agentResolve

function agentResolve(
    uint256 buyerBps,
    uint256 sellerBps
) external; // Agent only, -> AGENT_RESOLVED

proposeSplit / approveSplit / executeSplit

function proposeSplit(uint256 buyerBps, uint256 sellerBps) external;
function approveSplit() external;
function executeSplit() external;

Events

EscrowFactory Events

event EscrowCreated(
    address indexed escrow,
    address indexed buyer,
    address indexed seller,
    address agent,
    address token,
    uint256 amount,
    uint256 fee
);

EscrowImplementation Events

event Accepted(address indexed seller);
event Declined(address indexed seller);
event Fulfilled(address indexed seller, uint256 timestamp);
event Released(address indexed buyer, uint256 amount);
event Refunded(address indexed seller, uint256 amount);
event DisputeOpened(address indexed buyer);
event AgentInvited(address indexed inviter, address agent);
event AgentResolved(address agent, uint256 buyerAmount, uint256 sellerAmount);
event SplitProposed(address indexed proposer, uint256 buyerBps, uint256 sellerBps);
event SplitExecuted(uint256 buyerAmount, uint256 sellerAmount);

Integration Guide

Learn how to integrate →