Overview
x402r uses the factory pattern with CREATE2 for gas-efficient, deterministic contract deployments. Factories enable on-demand instance creation with predictable addresses.Why factories
Deterministic Addresses (CREATE2)
Deterministic Addresses (CREATE2)
Addresses are predictable before deployment, enabling:
- Off-chain address generation
- Cross-chain address consistency
- Contract-to-contract communication without registries
Idempotent Deployments
Idempotent Deployments
Calling a factory with the same parameters returns the existing contract:
- Safe to call again
- No duplicate deployments
- Built-in deduplication
Gas Optimization
Gas Optimization
Singleton conditions deployed once, reused everywhere:
- PayerCondition, ReceiverCondition deployed once
- All operators share the same condition instances
- Minimal storage overhead
Payment Operator Factory
Deploys PaymentOperator instances with deterministic addresses.Contract Address
All factories use universal CREATE2 addresses (same on every chain). PaymentOperatorFactory:0xa0d4734842df1690a5B33Cb21828c946e39D55a2
Configuration Structure
Deployment Method
feeReceiver- Who receives operator fees (arbiter, service provider, or treasury)authorizePreActionConditionthroughrefundPostActionHook- 10-slot configuration
maxFeeBps and protocolFeePct (shared across all operators)
Returns: Address of deployed operator (or existing if already deployed)
Address Prediction
Predict the operator address before deployment:Example Deployment
Marketplace Operator
Subscription Operator
Escrow Period Factory
DeploysEscrowPeriod contracts - combined hook and condition for time-based capture logic.
Contract Address
EscrowPeriodFactory:0xe72D2014ebC48F1d92521e8629574918E8030548
Deployment Method
escrowPeriod- Duration in seconds (for example,7 * 24 * 60 * 60for 7 days)authorizedCodehash- Runtime codehash of authorized caller (bytes32(0)= operator-only)
How It Works
The factory deploys a single EscrowPeriod contract that:- Extends
AuthorizationTimeRecorderHook(implementsIHook) - Implements
ICondition - Records authorization timestamp when used as hook
- Checks if escrow period has passed when used as condition
Use the SAME
EscrowPeriod address for both AUTHORIZE_POST_ACTION_HOOK and CAPTURE_PRE_ACTION_CONDITION slots on the operator. For freeze functionality, deploy a separate Freeze condition and compose via AndCondition([escrowPeriod, freeze]).Example Deployment
Common Escrow Periods
Freeze Factory
DeploysFreeze condition contracts that block capture when the payer freezes a payment.
Contract Address
FreezeFactory:0xeC092cf1215DB44af0Abe87c1157E304FEa5d0Eb
Deployment Method
freezeCondition- ICondition that gates freeze calls (for example, PayerCondition)unfreezeCondition- ICondition that gates unfreeze calls (for example, PayerCondition or ArbiterCondition)freezeDuration- How long freeze lasts in seconds (0= permanent until unfrozen)escrowPeriodContract- Address of EscrowPeriod contract (address(0)= freeze unconstrained by time)
Full Freeze Deployment Example
Condition Singletons
Reference the pre-deployed condition singletons (PayerCondition, ReceiverCondition, AlwaysTrueCondition) by their canonical addresses. The full address registry lives on Periphery Overview: Condition Singletons, identical across every supported chain.Example Deployments
- Payer Freeze
- Receiver Freeze
- Payer OR Receiver
- Arbiter Controlled
Payer can freeze, arbiter can unfreeze (or it expires after 3 days):
Freeze Duration Guidelines
Factory Ownership
A multisig wallet owns all factories for security.Owner Capabilities
Factory owners can:- Update factory configuration (if mutable fields exist)
- Rescue stuck ETH (via
rescueETH()) - Transfer ownership (2-step process)
- Change deployed instances
- Pause or stop operations
- Access funds in deployed operators
Ownership Transfer
Gas Costs
Approximate gas costs for factory deployments (Base Sepolia):CREATE2 Details
Salt Generation
Each factory uses different salt strategies: PaymentOperatorFactory:Cross-Chain Addresses
Because the factory uses CREATE2, the same configuration produces the same operator address on any chain where the factory itself lives at the canonical address. As supported chains expand beyond Base, an operator deployed with identical config will land at the same address on each new chain without the integrator needing per-chain bookkeeping. This enables:- Consistent addressing across chains
- Simplified multi-chain integrations
- Predictable contract locations
Best Practices
1. Predict Before Deploy
Always verify predicted address before deployment:2. Reuse Condition Singletons
Don’t deploy new PayerCondition/ReceiverCondition - use existing singletons:3. Test Configuration First
Deploy on testnet with same configuration before mainnet:4. Document your config
Keep a record of your deployed configurations:Next Steps
Conditions
Learn about the pluggable condition system.
Examples
See real-world configuration examples.
Deploy an Operator
Use the SDK’s
deployMarketplaceOperator() for simplified deployment.SDK Overview
Install the SDK packages.
