x402Escrow
Deploy
Clone and Build
git clone https://github.com/Fortytwo-Network/fortytwo-x402Escrow.git
cd fortytwo-x402Escrow
forge install
forge build
Run Tests
All 43 tests should pass, covering initialization, settlement, release, refunds, role management, upgrades, and edge cases.
Check Gas Usage
Compares current gas usage against the committed baseline in .gas-snapshot.
Supported Networks
| Network | Chain ID | USDC Address | Deployed Escrow |
|---|
| Base | 8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | 0x9562f50f73d8ee22276f13a18d051456d8d137a0 |
| Base Sepolia | 84532 | 0x036CbD53842c5426634e7929541eC2318f3dCF7e | 0x9562f50f73d8ee22276f13a18d051456d8d137a0 |
| Monad | 143 | 0x754704Bc059F8C67012fEd69BC8A327a5aafb603 | 0x9562f50f73d8ee22276f13a18d051456d8d137a0 |
| Monad Testnet | 10143 | 0x534b2f3A21130d7a60830c2Df862319e593943A3 | 0x9562f50f73d8ee22276f13a18d051456d8d137a0 |
Environment Setup
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:
- x402Escrow implementation — the contract logic.
- ERC1967Proxy — the proxy that delegates to the implementation and holds all state.
Local (Anvil)
Base
Monad
Base Sepolia (Testnet)
Monad Testnet
Start a local node:In a new terminal:source .env
forge script script/DeployX402Escrow.s.sol \
--rpc-url http://127.0.0.1:8545 \
--broadcast
source .env
forge script script/DeployX402Escrow.s.sol \
--rpc-url base \
--broadcast \
--verify
source .env
forge script script/DeployX402Escrow.s.sol \
--rpc-url monad \
--broadcast
forge script script/DeployX402Escrow.s.sol \
--rpc-url base_sepolia \
--broadcast \
--verify
forge script script/DeployX402Escrow.s.sol \
--rpc-url monad_testnet \
--broadcast \
--verify
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:
- Deploy the new implementation contract.
- 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