Skip to main content

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

FieldTypeDescription
zone_idstringZone where the action is defined
actionstringAction name being requested
tostringContract address to send the payment to (ZoneSettlement or ZoneEscrow)
recipientstringSteward’s wallet address (receives net amount after fees)
amountstringTotal amount in raw USDC units (6 decimals)
assetstringPayment asset (currently always "USDC")
tokenstringERC-20 token contract address on the active chain
chain_idu64Chain ID (8453 for Base mainnet, 84532 for testnet)
deadlinei64Unix timestamp by which the payment must be submitted (typically now + 300s)
noncestringUnique nonce for the payment authorization
settlement_modestring?"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

FieldTypeDescription
fromstringPayer’s wallet address
tostringMust match the to in PaymentRequirement
valuestringMust match the amount in PaymentRequirement
valid_afteru64Earliest timestamp the authorization is valid (typically 0)
valid_beforeu64Must be at or before the deadline and in the future
noncestringMust match the nonce in PaymentRequirement
vu8ECDSA signature recovery parameter
rstringECDSA signature r component (bytes32 hex)
sstringECDSA signature s component (bytes32 hex)

Validation rules

The steward validates the authorization before executing on-chain:
  1. to must match (case-insensitive) the contract in the payment requirement
  2. value must exactly match the required amount
  3. nonce must exactly match the required nonce
  4. 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:
FieldTypeDescription
deadlinei64Unix 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

ContractPurposeAddress
ZoneSettlementDirect settlement with fee splitting0x3BdFbd10a2992a7e83521e8249B67F1f430a67a4
ZoneEscrowEscrow deposit, release, refund, dispute0x633411f26D7138273Cb1183147530d65C754E098
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:
ComponentRateCalculation
Protocol fee0.1% (10 bps)total * 10 / 10000
Creator fee0—3% (0—300 bps)total * creator_fee_bps / 10000
Recipient amountRemaindertotal - protocol_fee - creator_fee
Escrow deposits lock the full amount. Fee splitting occurs at release time.