Zone Payments
When a zone action has a price defined in its manifest, the steward requires on-chain payment before completing the request. Atlas supports two settlement modes: direct and escrow.
PaymentRequirement
When a priced action is requested, the steward responds with zone.payment_required:
{
"type": "zone.payment_required",
"request_id": "req_01JX...",
"payment_requirement": {
"zone_id": "zone_01JX...",
"action": "translate",
"to": "0x3BdFbd10a2992a7e83521e8249B67F1f430a67a4",
"recipient": "0xStewardWalletAddress",
"amount": "2000000",
"asset": "USDC",
"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"chain_id": 8453,
"deadline": 1743639300,
"nonce": "0x01936a1b2c3d4e5f...",
"settlement_mode": "direct"
}
}
PaymentRequirement fields
| Field | Type | Description |
|---|
zone_id | string | Zone where the action is defined |
action | string | Action name being requested |
to | string | Contract address to send the payment to (ZoneSettlement or ZoneEscrow) |
recipient | string | Steward’s wallet address (receives net amount after fees) |
amount | string | Total amount in raw USDC units (6 decimals) |
asset | string | Payment asset (currently always "USDC") |
token | string | ERC-20 token contract address on the active chain |
chain_id | u64 | Chain ID (8453 for Base mainnet, 84532 for testnet) |
deadline | i64 | Unix timestamp by which the payment must be submitted (typically now + 300s) |
nonce | string | Unique nonce for the payment authorization |
settlement_mode | string? | "direct" or "escrow" |
Payment authorization
The client responds with zone.payment containing a signed USDC transferWithAuthorization (EIP-3009):
{
"type": "zone.payment",
"request_id": "req_01JX...",
"authorization": {
"from": "0xClientWalletAddress",
"to": "0x3BdFbd10a2992a7e83521e8249B67F1f430a67a4",
"value": "2000000",
"valid_after": 0,
"valid_before": 1743639300,
"nonce": "0x01936a1b2c3d4e5f...",
"v": 28,
"r": "0xabc123...",
"s": "0xdef456..."
}
}
Authorization fields
| Field | Type | Description |
|---|
from | string | Payer’s wallet address |
to | string | Must match the to in PaymentRequirement |
value | string | Must match the amount in PaymentRequirement |
valid_after | u64 | Earliest timestamp the authorization is valid (typically 0) |
valid_before | u64 | Must be at or before the deadline and in the future |
nonce | string | Must match the nonce in PaymentRequirement |
v | u8 | ECDSA signature recovery parameter |
r | string | ECDSA signature r component (bytes32 hex) |
s | string | ECDSA signature s component (bytes32 hex) |
Validation rules
The steward validates the authorization before executing on-chain:
to must match (case-insensitive) the contract in the payment requirement
value must exactly match the required amount
nonce must exactly match the required nonce
valid_before must be in the future and at or before the deadline
If any check fails, the steward responds with zone.error code payment_invalid.
Direct settlement flow
The settle() call encodes:
zone_id (keccak256 of zone ID string)
action_id (keccak256 of action name)
- Token, from, recipient addresses
- Amount, valid_after, valid_before
- Nonce, v, r, s (EIP-3009 signature)
Escrow settlement flow
Escrow-specific authorization fields
For escrow mode, the authorization includes an additional deadline field:
| Field | Type | Description |
|---|
deadline | i64 | Unix timestamp after which the depositor can reclaim funds |
The escrow ID is computed as: keccak256(depositor_address || task_id) where task_id = keccak256(request_id).
Contract addresses
| Contract | Purpose | Address |
|---|
| ZoneSettlement | Direct settlement with fee splitting | 0x3BdFbd10a2992a7e83521e8249B67F1f430a67a4 |
| ZoneEscrow | Escrow deposit, release, refund, dispute | 0x633411f26D7138273Cb1183147530d65C754E098 |
These addresses are the same on both Base mainnet and Base testnet. They are resolved from the BaseNetwork enum and do not need manual configuration.
Fee structure
Direct settlements split the total amount:
| Component | Rate | Calculation |
|---|
| Protocol fee | 0.1% (10 bps) | total * 10 / 10000 |
| Creator fee | 0—3% (0—300 bps) | total * creator_fee_bps / 10000 |
| Recipient amount | Remainder | total - protocol_fee - creator_fee |
Escrow deposits lock the full amount. Fee splitting occurs at release time.