Skip to main content
x402Escrow Deploy
Prerequisites:
Foundry installed
Git installed

Clone and Build

git clone https://github.com/Fortytwo-Network/fortytwo-x402Escrow.git
cd fortytwo-x402Escrow
forge install
forge build

Run Tests

forge test -vv
All 43 tests should pass, covering initialization, settlement, release, refunds, role management, upgrades, and edge cases.

Check Gas Usage

forge snapshot --check
Compares current gas usage against the committed baseline in .gas-snapshot.

Supported Networks

NetworkChain IDUSDC AddressDeployed Escrow
Base84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA029130x9562f50f73d8ee22276f13a18d051456d8d137a0
Base Sepolia845320x036CbD53842c5426634e7929541eC2318f3dCF7e0x9562f50f73d8ee22276f13a18d051456d8d137a0
Monad1430x754704Bc059F8C67012fEd69BC8A327a5aafb6030x9562f50f73d8ee22276f13a18d051456d8d137a0
Monad Testnet101430x534b2f3A21130d7a60830c2Df862319e593943A30x9562f50f73d8ee22276f13a18d051456d8d137a0

Environment Setup

cp .env.example .env
PRIVATE_KEY=0x...                    # Deployer private key
USDC_ADDRESS=0x...                   # Network-specific USDC
FACILITATOR_ADDRESS=0x...            # Initial facilitator
ADMIN_ADDRESS=0x...                  # Initial admin (DEFAULT_ADMIN_ROLE)
OWNER_ADDRESS=0x...                  # Contract owner (UUPS upgrade auth)
.gitignore excludes .env from commits. Never commit .env to version control.

Deploy

The deployment script deploys two contracts:
  1. x402Escrow implementation — the contract logic.
  2. ERC1967Proxy — the proxy that delegates to the implementation and holds all state.
Start a local node:
anvil
In a new terminal:
source .env
forge script script/DeployX402Escrow.s.sol \
  --rpc-url http://127.0.0.1:8545 \
  --broadcast
The script outputs both the implementation and proxy addresses. Use the proxy address for all interactions.

Post-Deployment Verification

# Check USDC address
cast call <PROXY_ADDRESS> "usdc()(address)" --rpc-url base

# Check timeout (should be 5400 = 90 min)
cast call <PROXY_ADDRESS> "timeoutSecs()(uint256)" --rpc-url base

# Check facilitator role
cast call <PROXY_ADDRESS> "hasRole(bytes32,address)(bool)" \
  $(cast call <PROXY_ADDRESS> "FACILITATOR_ROLE()(bytes32)" --rpc-url base) \
  <FACILITATOR_ADDRESS> \
  --rpc-url base

# Check admin role
cast call <PROXY_ADDRESS> "hasRole(bytes32,address)(bool)" \
  0x0000000000000000000000000000000000000000000000000000000000000000 \
  <ADMIN_ADDRESS> \
  --rpc-url base

# Check owner
cast call <PROXY_ADDRESS> "owner()(address)" --rpc-url base
If deployed with --verify, the source code appears on Basescan. Otherwise, verify manually:
forge verify-contract <IMPLEMENTATION_ADDRESS> src/X402Escrow.sol:X402Escrow \
  --rpc-url base \
  --watch

Role Management

export ADMIN_KEY=0x...  # Private key of the DEFAULT_ADMIN_ROLE holder

Add a Facilitator

cast send <PROXY_ADDRESS> \
  "grantRole(bytes32,address)" \
  $(cast call <PROXY_ADDRESS> "FACILITATOR_ROLE()(bytes32)" --rpc-url base) \
  <NEW_FACILITATOR> \
  --private-key $ADMIN_KEY \
  --rpc-url base

Remove a Facilitator

cast send <PROXY_ADDRESS> \
  "revokeRole(bytes32,address)" \
  $(cast call <PROXY_ADDRESS> "FACILITATOR_ROLE()(bytes32)" --rpc-url base) \
  <OLD_FACILITATOR> \
  --private-key $ADMIN_KEY \
  --rpc-url base

Adjust Timeout

cast send <PROXY_ADDRESS> \
  "setTimeout(uint256)" \
  3600 \
  --private-key $ADMIN_KEY \
  --rpc-url base
Valid range: 300 (5 minutes) to 86400 (24 hours).

Upgrade Procedure

x402Escrow uses the UUPS proxy pattern. To upgrade:
  1. Deploy the new implementation contract.
  2. Call upgradeToAndCall() on the proxy from the Owner address.
export OWNER_KEY=0x...  # Private key of the contract owner

# Deploy new implementation
forge create src/<YOUR_V2_CONTRACT>.sol:<YOUR_V2_CONTRACT> \
  --rpc-url base \
  --private-key $OWNER_KEY

# Upgrade proxy to new implementation
cast send <PROXY_ADDRESS> \
  "upgradeToAndCall(address,bytes)" \
  <NEW_IMPLEMENTATION> \
  0x \
  --private-key $OWNER_KEY \
  --rpc-url base
When deploying your contract, maintain storage layout compatibility. Do not reorder or remove existing state variables.

Production Checklist

  • Deploy with a hardware wallet or multisig as the Owner
  • Use separate addresses for Owner, Admin, and Facilitator roles
  • Verify contract source on block explorer
  • Confirm USDC address is correct for the target network
  • Confirm timeoutSecs is appropriate for your use case
  • Set up event monitoring for Deposited, Released, and Refunded
  • Test a full escrow cycle (settle -> release) on testnet before mainnet
  • Ensure .env is listed in .gitignore