Skip to main content
The @x402r/core package includes deployment utilities that handle the full lifecycle of deploying a PaymentOperator and all its supporting contracts.

Overview

A complete marketplace operator deployment includes:
  1. EscrowPeriod — Records authorization time, enforces waiting period before release
  2. Freeze — Allows payer to freeze payment during escrow, receiver to unfreeze
  3. StaticAddressCondition — Restricts refund approval to the designated arbiter
  4. OrCondition — Allows either the receiver OR the arbiter to approve in-escrow refunds
  5. StaticFeeCalculator — Optional operator fee (basis points)
  6. PaymentOperator — The main contract tying everything together
All contracts are deployed via factories using CREATE2, so identical configurations produce identical addresses across deployments.

Quick Deploy

import { createPublicClient, createWalletClient, http } from 'viem';
import { baseSepolia } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import { deployMarketplaceOperator } from '@x402r/core/deploy';

const publicClient = createPublicClient({
  chain: baseSepolia,
  transport: http(),
});

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
  account,
  chain: baseSepolia,
  transport: http(),
});

const result = await deployMarketplaceOperator(
  walletClient,
  publicClient,
  'eip155:84532', // Base Sepolia
  {
    feeRecipient: '0xYourAddress...',    // receives operator fees
    arbiter: '0xArbiterAddress...',       // dispute resolver
    escrowPeriodSeconds: 604800n,         // 7 days
    operatorFeeBps: 100n,                 // 1% fee (optional)
  }
);

console.log('Operator:', result.operatorAddress);
console.log('EscrowPeriod:', result.escrowPeriodAddress);
console.log('Freeze:', result.freezeAddress);
console.log('New deployments:', result.summary.newDeployments);
console.log('Existing (reused):', result.summary.existingContracts);

Configuration Options

OptionTypeDescription
feeRecipientAddressAddress that receives operator fees
arbiterAddressArbiter address for dispute resolution
escrowPeriodSecondsbigintEscrow waiting period (e.g., 604800n for 7 days)
freezeDurationSecondsbigintHow long freezes last. Default: 0n (permanent until unfrozen)
operatorFeeBpsbigintFee in basis points. Default: 0n (no fee). 100n = 1%

Deployment Result

The deployMarketplaceOperator function returns:
interface MarketplaceOperatorDeployment {
  operatorAddress: Address;           // The PaymentOperator
  escrowPeriodAddress: Address;       // EscrowPeriod recorder/condition
  freezeAddress: Address;             // Freeze condition
  arbiterConditionAddress: Address;   // StaticAddressCondition for arbiter
  refundInEscrowCondition: Address;   // OR(Receiver, Arbiter)
  feeCalculatorAddress: Address | null; // null if no fee
  txHashes: Hash[];                   // All deployment tx hashes
  summary: {
    newDeployments: number;           // Newly deployed contracts
    existingContracts: number;        // Reused existing contracts
  };
}
Because all contracts use CREATE2, redeploying with the same parameters is idempotent — it will detect existing contracts and skip them. The summary tells you what was new vs reused.

Preview Addresses (No Deploy)

You can preview what addresses will be created without actually deploying:
import { previewMarketplaceOperator } from '@x402r/core/deploy';

const preview = await previewMarketplaceOperator(
  publicClient,
  'eip155:84532',
  {
    feeRecipient: '0xYourAddress...',
    arbiter: '0xArbiterAddress...',
    escrowPeriodSeconds: 604800n,
  }
);

console.log('Operator will be at:', preview.operatorAddress);
console.log('EscrowPeriod will be at:', preview.escrowPeriodAddress);

Operator Slot Configuration

The deployed operator has the following slot configuration:
SlotContractPurpose
AUTHORIZE_CONDITIONUsdcTvlLimitSafety limit on authorization
AUTHORIZE_RECORDEREscrowPeriodRecords authorization timestamp
CHARGE_CONDITION(none)No restrictions on charge
RELEASE_CONDITIONEscrowPeriodBlocks release during escrow period
REFUND_IN_ESCROW_CONDITIONOR(Receiver, Arbiter)Receiver or arbiter can approve
REFUND_POST_ESCROW_CONDITIONReceiverOnly receiver after escrow
FEE_CALCULATORStaticFeeCalculatorFixed percentage fee
FEE_RECIPIENTYour addressReceives fees

Network Support

Deployment is supported on both networks:
NetworkChain IDEIP-155 ID
Base Sepolia84532eip155:84532
Base Mainnet8453eip155:8453
Deployment requires gas fees. Ensure your wallet has ETH on the target network. On Base Sepolia, you can get testnet ETH from the Base Sepolia Faucet.

Next Steps