Chio/Docs

EconomyCost & Settlement

On-Chain Settlement

Web3 settlement uses five contracts, two release paths, and a nine-state escrow lifecycle on EVM and Solana.

Use this page when

Use this page to integrate Web3 contracts, release paths, EVM/Solana helpers, and CCIP coordination. For the settlement-method matrix, see Settlement Rails) . For chain-by-chain configuration, see Integrations / Settlement).

Where this fits

This page is the economy view of on-chain settlement. The chain-by-chain integration reference (which networks, which assets, gas profiles) lives in Integrations / Settlement. The chio-side rail abstraction lives in Settlement Rails.
Settlement rail comparison matrixLatencylower is betterFinalitystronger is betterCost per txnlower is betterTrust requiredlower is betterRail kind: ManualManualhuman invoice / checkRail kind: ApiApiStripe · Adyen · …Rail kind: AchAchbank ACH fileRail kind: WireWirewire transferRail kind: LedgerLedgerinternal entriesRail kind: SandboxSandboxdev / testRail kind: Web3Web3on-chain escrowDays to weeks; human-paced.highReversible; recorded by hand.lowOperator labour, dispute risk.med-highCounterparty must be reachable and willing.highSub-second authorize; capture in seconds to minutes.lowChargeback / refund window; finality after dispute deadline.mediumPer-txn processor fees and interchange.mediumTrust the processor and the counterparty bank.mediumBank business days; same-day ACH on some rails.1-3 daysFinal once cleared; reversal limited to errors / fraud.highCents per transaction.lowPre-authorised debit relationship required.mediumSame-day; minutes to hours during banking hours.lowIrrevocable on receipt.highFlat fee per wire; expensive at low ticket sizes.highBanking relationship and account verification required.mediumSynchronous in-process write.very lowFinal inside the operator's books; not externally enforceable.within orgBookkeeping cost only.very lowSingle-org cost allocation; no external counterparty.n/aSynthetic; whatever the fixture asks for.very lowNo external settlement; the lifecycle is scripted.n/aNo funds move.noneAvailable in tests and disabled in production.n/aBlock-confirmation latency; faster on L2s, slower on L1s.mediumProbabilistic-final after sufficient confirmations; checkpoint-anchored.very highGas-priced; varies with chain congestion.med-high gasTrustless: escrow contract enforces dual-signature or merkle release.very lowscale: 4 segments · tone reads value-for-operatorfavourableneutralunfavourableempty cell = attribute not applicable for this railsource: CapitalExecutionRailKind (chio-credit)
Compare settlement methods by counterparty type, finality, cost, latency, and required trust.

The Five Contracts

Every chio Web3 deployment ships the same five interfaces, addressed as Web3ContractKind in chio-web3. Chain-specific addresses live in the per-chain Web3ChainDeployment, but the ABI and the role of each contract are stable.

ContractRole
ChioRootRegistryAnchors checkpoint roots published by the kernel. Every merkle release verifies a leaf against a root that has already been registered here.
ChioEscrowLocks funds against a capability commitment. Holds the dispatch reference, the agreed amount, and the lifecycle state. Settles via dual signature or merkle proof.
ChioBondVaultHolds bonds (operator collateral, agent collateral) that back high-trust capabilities. Bonds can be released, expired, or impaired against a slashing event.
ChioIdentityRegistryBinds chio public keys to on-chain settlement addresses. The contract checks that the binding the operator presents has the correct purpose (settle, publish) and chain scope.
ChioPriceResolverReturns FX prices from the configured oracle when a receipt is denominated in a non-native asset. Used by escrow on release to compute the settlement amount in the chain's settlement token.

Bindings ship as Rust types in chio-web3-bindings, with Solidity ABIs versioned alongside the kernel. The chio-settle/src/evm/ module drives these contracts and records on-chain state in the receipt records.

Payment Channels build on this same ChioEscrow: one bounded deposit is funded up front, many high-frequency low-value calls stream against a single cumulative signed amount, and the channel settles once at cooperative or contested close rather than dispatching a separate escrow per call.


Two Settlement Paths

Once an escrow is locked, releasing it is a choice between two paths. The kernel encodes the choice in Web3SettlementPath:

chio-web3/src/trust_profile.rs
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Web3SettlementPath {
    DualSignature,
    MerkleProof,
}

DualSignature (Fast Path)

Both parties sign the release. The provider signs an EIP-712 digest binding the receipt hash, the observed amount, and the escrow id; the contract recovers the signature and credits the beneficiary. Latency is a single block confirmation; gas matches a normal token transfer plus a digest verification.

Use when the buyer remains online and cooperative. This is the common path: agent calls tool, tool returns, buyer counter-signs the release, funds settle, total wall-clock is one block.

MerkleProof (Trustless Fallback)

The provider produces an inclusion proof: this receipt is a leaf in a published merkle tree, the root of which has been registered in ChioRootRegistry. The escrow contract verifies the proof against the root and releases without ever needing the buyer's signature.

Use when the buyer has gone offline, is uncooperative, or simply cannot sign within the dispute window. The trade is a heavier transaction (one merkle verification plus a root lookup) and a longer wall-clock (the receipt has to be in a checkpoint that has already been published, which is bounded by the operator's checkpoint cadence).

The roots themselves are anchored by the chio-anchor crate, which publishes signed checkpoint statements containing checkpoint_seq, batch_start_seq, batch_end_seq, tree_size, and the merkle root. A merkle release proof can be verified from the chain-registered root and the receipt's leaf hash; the verifier does not need to trust the operator.

Settlement path is chosen per dispatch

A single contract supports both paths. The dispatch record picks which one this particular settlement should use; the operator can ship some flows on dual-signature and others on merkle, and the same escrow address handles both.

Escrow Lifecycle States

The kernel's view of an escrow's state is Web3SettlementLifecycleState in chio-web3. Nine variants:

chio-web3/src/settlement.rs
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Web3SettlementLifecycleState {
    PendingDispatch,
    EscrowLocked,
    PartiallySettled,
    Settled,
    Reversed,
    ChargedBack,
    TimedOut,
    Failed,
    Reorged,
}
StateMeaning
pending_dispatchA signed dispatch record exists; no on-chain transaction has been observed.
escrow_lockedFunds locked in ChioEscrow; awaiting release.
partially_settledA partial release has paid out; remainder still locked.
settledRelease executed; funds delivered to beneficiary; finality confirmed.
reversedRefund executed before release; funds returned to depositor.
charged_backPost-settlement reversal; an off-chain dispute clawback has been recorded.
timed_outDispute window expired without release; refund recovery is the next action.
failedOn-chain submission reverted; the dispatch needs to be retried or escalated.
reorgedA previously confirmed settlement has been undone by a chain reorg; resubmission required.

On-chain terminal states and kernel records

Per ADR-0015, the ChioEscrow contract itself has two predeclared, price-free terminal outcomes: release-on-proof (either settlement path above) or refund-after-deadline. The contract has no admin, pause, or emergency path. The nine-variant Web3SettlementLifecycleState above, including ChargedBack and Reversed, is kernel-side records of settlement outcomes, including off-chain disputes and reorg handling. They do not give the escrow contract discretionary power. charged_back is not an on-chain clawback: the contract has already reached a terminal outcome when the kernel records that state. Web3SettlementSupportBoundary.real_dispatch_supported defaults to false, and no mainnet deployment is authorized while it does.

Lifecycle Diagram

Web3 escrow settlement lifecyclePendingDispatch: signed dispatch record; on-chain transaction not yet observedPendingDispatchtx not yet observedEscrowLocked: funds locked in ChioEscrow awaiting releaseEscrowLockedfunds heldPartiallySettled: a partial release has paid out; remainder still lockedPartiallySettledremainder lockedSettled: release executed; funds delivered; finality confirmedSettledfinality confirmedFailed: on-chain submission reverted; retry or escalateFailedtx revertedReorged: a previously confirmed settlement has been undone by a chain reorgReorgedchain reorgTimedOut: dispute window expired without release; refund recovery is nextTimedOutdispute windowReversed: refund executed before release; funds returned to depositorReversedrefund executedChargedBack: post-settlement reversal; an off-chain dispute clawback has been recordedChargedBackpost-settle clawbacktx confirmedpartial releasefull releaseremainder releasedtx revertedretryreorgresubmitwindow expiredwindow expiredrefundexecute refundclawbackreorg observedhappy path: PendingDispatch -> EscrowLocked -> SettledReversed, ChargedBack, TimedOut, Failed, Reorged are recoverable failure terminalssolid = forward progression · dashed = recovery / failure transition
The normal sequence is PendingDispatch -> EscrowLocked -> Settled. Reversal, chargeback, and timeout move the escrow into recovery states.

EVM Support

EVM coverage lives in the chio-settle/src/evm/ module, organized into mod.rs, types.rs (the Prepared* request and response types), prepare.rs (the prepare_* constructor), and finalize.rs (the confirm and finality helpers). Dispatch and release calls are constructed as PreparedEvmCall values (from_address, to_address, data, optional gas limit) ready for an external signer to sign and broadcast.

The supported entry points cover the full lifecycle:

  • prepare_web3_escrow_dispatch: build a PreparedEscrowCreate from a signed capital-execution instruction.
  • prepare_dual_sign_release: build a PreparedDualSignRelease with the EIP-712 digest pre-signed by the operator key.
  • prepare_merkle_release: build a PreparedMerkleRelease carrying the receipt leaf hash, the root, and the proof path.
  • prepare_escrow_refund: build the refund call once the dispute window expires.
  • prepare_bond_lock / prepare_bond_release / prepare_bond_impair: drive the ChioBondVault over its lifecycle.
  • prepare_erc20_approval: emit the ERC-20 approve() call needed before the escrow can pull tokens.

State-changing calls are signed by an external wallet or signer service; the Chio kernel does not hold transaction private keys. The exception is the operator's signing key for dual-signature digests, which is presented as a hex-encoded private key only at the call site that produces the digest.

The shipped deployment templates target two EVM environments: Base (eip155:8453) as the primary execution and anchoring environment, and Arbitrum One (eip155:42161) as the bounded secondary. The integration page lists per-chain details. Finality is captured as Web3FinalityMode (OptimisticL2, L1Finalized, SolanaConfirmed) per deployment, with a minimum-confirmation count attached.

No mainnet deployment is authorized yet

The contract package is not approved for mainnet deployment, non-testnet custody, or non-testnet promotion. External audit, testnet soak, contract digest, runtime codehash, minimum-bar checklist, and security-owner sign-off are all required before non-testnet use. Until that assurance passes, the allowed environments are local devnet, runtime devnet, and the Base Sepolia public-testnet rehearsal; the Base and Arbitrum One templates stay template-stage. Local qualification reports and prior contract security reviews are historical evidence, not promotion approval.

Solana Support

Solana support covers local verification and instruction preparation. chio-settle does not broadcast a Solana transaction, run an on-chain Solana program, or index the cluster. Code lives in chio-settle/src/solana.rs.

The dispatch model is narrower than EVM: there is no escrow contract holding funds during execution. prepare_solana_settlement verifies the receipt and binding, then emits a PreparedSolanaSettlement carrying the receipt signature, the Ed25519 program id (Ed25519SigVerify111111111111111111111111111), the chio public key, and a canonical chio.settle.solana-release.v1 instruction payload in instruction_data_hex. An external submitter assembles and broadcasts the transaction that pairs the native Ed25519 signature check with the SPL token transfer; chio-settle prepares and verifies the transaction but does not broadcast it. compare_commitments reconciles the prepared commitment against the observed one and reports a CommitmentConsistencyReport for parity checks.

chio-settle/src/solana.rs
pub struct PreparedSolanaSettlement {
    pub dispatch_id: String,
    pub chain_id: String,
    pub cluster: String,
    pub program_id: String,
    pub payer_address: String,
    pub beneficiary_address: String,
    pub settlement_mint: String,
    pub capability_commitment: String,
    pub receipt_hash: String,
    pub settlement_amount_minor_units: u64,
    pub recent_blockhash: String,
    pub ed25519_program_id: String,
    pub ed25519_signature: String,
    pub chio_public_key: String,
    pub instruction_data_hex: String,
    pub note: Option<String>,
}

The kernel-side helper verify_solana_binding_and_receipt confirms the binding has the settle purpose, the chain scope covers the target chain, and the settlement address decodes as a valid base58 Solana address before allowing the dispatch to be prepared.


Cross-Chain via Chainlink CCIP

For settlements that span chains (settle on Base, but the depositor funded escrow from Arbitrum, say) the kernel ships a CCIP message envelope in chio-settle/src/ccip.rs. It is not a bridge; it is a typed coordination layer over Chainlink's Cross-Chain Interoperability Protocol that lets a settlement event on one chain to be reconciled with state on another.

chio-settle/src/ccip.rs
pub struct CcipLaneConfig {
    pub source_chain_id: String,
    pub destination_chain_id: String,
    pub router_address: String,
    pub max_payload_bytes: usize,
    pub max_execution_gas: u64,
    pub expected_latency_secs: u64,
}

pub enum CcipMessageStatus {
    Prepared,
    Reconciled,
    DuplicateSuppressed,
    Delayed,
    Unsupported,
}

prepare_ccip_settlement_message validates the lane (source != destination, payload bounds non-zero, validity window at least twice the expected latency), then assembles a payload containing the dispatch id, execution receipt id, settlement reference, lifecycle state, settled amount, and beneficiary address. reconcile_ccip_delivery cross-checks the SHA-256 digest of the delivered payload against the digest the kernel originally signed.

Use CCIP when:

  • The escrow chain and the bond vault chain are different (operator on Ethereum, escrow on Base).
  • A multi-chain operator needs one settlement event delivered to several treasury locations.
  • The integration partner already speaks CCIP and won't accept a bespoke bridge.

For typical single-chain flows, plain EVM dispatch on the same chain is simpler and cheaper. The full Chainlink integration view lives at Integrations / Chainlink.


Worked Example

An agent calls a tool that costs 1.50 USDC. The capability is bound to the Web3 rail on Base with aDualSignature path.

Happy Path: DualSignature

  1. Kernel signs a capital-execution instruction for 1.50 USDC. prepare_web3_escrow_dispatch builds a PreparedEscrowCreate.
  2. Operator's signer broadcasts the dispatch tx. The escrow contract locks 1.50 USDC. State: EscrowLocked.
  3. Tool runs. Observed cost matches the quoted 1.50 USDC.
  4. Operator presents prepare_dual_sign_release to the buyer. Buyer counter-signs the EIP-712 digest.
  5. Combined signatures broadcast to the contract; release executes; funds credited to beneficiary. State: Settled after the configured confirmation count is reached.

Total wall-clock from tool completion to settled status: a single block confirmation on Base, typically two seconds.

Fallback: MerkleProof

Same scenario, but the buyer goes offline before counter-signing.

  1. State remains EscrowLocked until the dispute window opens for an alternate release.
  2. The kernel publishes a checkpoint covering the receipt; the merkle root is registered in ChioRootRegistry by the anchor pipeline.
  3. Operator calls prepare_merkle_release with the receipt leaf hash, the registered root, and the proof path computed against the checkpoint tree.
  4. Contract verifies the proof against the registered root, confirms inclusion, and releases funds. State: Settled.
  5. If the dispute window expires without either path succeeding, the watchdog flips the state to TimedOut and the next recovery action is ExecuteRefund (the depositor gets their funds back).

Fallback latency is bounded by checkpoint cadence

Merkle release requires the receipt to be inside an already-published checkpoint. If the operator publishes checkpoints every ten minutes, the worst-case wait for the fallback is roughly that interval plus chain confirmation time. Tune the checkpoint cadence against the dispute window.

Checkpoint Anchoring

A Merkle release proof depends on the root it verifies. Roots come from chio-anchor: the kernel publishes batched checkpoints as Web3CheckpointStatement statements containing batch bounds, tree size, root, kernel public key, and signature. The anchor publishes those statements to theChioRootRegistry on each target chain so that any verifier (regulator, auditor, dispute resolver) can independently verify the inclusion proof.

ChioRootRegistry is one of four anchoring methods in chio-anchor ships. A merkle release depends only on the EVM registry, but the same batched checkpoint can be anchored by several methods for defense in depth:

  • EVM root registry (evm.rs): prepare_root_publication / confirm_root_publication against the ChioRootRegistry contract. A Merkle release verifies against this method.
  • Bitcoin via OpenTimestamps (bitcoin.rs): prepare_ots_submission / verify_ots_proof_for_submission.
  • Solana memo (solana.rs): prepare_solana_memo_publication / verify_solana_anchor.
  • Chainlink Functions (functions.rs): an off-chain attestation fallback.

Proof-bundle verification fails closed. verify_proof_bundle rejects the whole bundle if any single lane is bad; verify_proof_bundle_with_discovery adds freshness checks. A bad anchor invalidates the bundle; there is no partial pass.

The receipt-side proof record is Web3ReceiptInclusion with checkpoint_seq, merkle_root, and the proof path. verify_anchor_inclusion_proof in chio-web3 (the anchors module) is the authoritative verifier; Web3CheckpointStatement and Web3ReceiptInclusion are chio-web3 types re-exported through chio-anchor.


Finality and Recovery

Finality is observed via SettlementFinalityAssessment in chio-settle/src/observe.rs. Each chain configures a required confirmation count and a dispute window in seconds. Status is one of:

  • awaiting_confirmations: tx mined but not yet at the required depth.
  • awaiting_dispute_window: confirmed, but the optimistic challenge window is open.
  • finalized: confirmation count and dispute window both satisfied.
  • reorged: a previously confirmed tx is no longer in the canonical chain.

Recovery actions (SettlementRecoveryAction, seven variants) map onto the finality assessment and lifecycle state. While a tx is short of the required depth the action is WaitForConfirmations; while the optimistic challenge window is open it is WaitForDisputeWindow. Failed suggests RetrySubmission; TimedOut suggests ExecuteRefund; Reorged suggests ResubmitAfterReorg. The remaining variants are ManualReview and ExpireBond for the bond-vault lifecycle. The watchdog (next page) drives this automation.


Payments and Operational Controls

The escrow lifecycle above is the on-chain settlement core, but chio-settle carries two more settlement-adjacent modules in the same crate.

The payments module prepares the account-level payment rails that sit beside escrow dispatch:

  • build_x402_payment_requirements: assemble an x402 HTTP-402 payment requirement.
  • prepare_transfer_with_authorization: build an EIP-3009 transfer-with-authorization call.
  • evaluate_circle_nanopayment: evaluate a Circle nanopayment.
  • prepare_paymaster_compatibility: check ERC-4337 paymaster compatibility.

The ops module gates settlement operations behind an emergency-mode switch. SettlementEmergencyMode has five states ( Normal, DispatchPaused, RefundOnly, RecoveryOnly, and Halted) and ensure_settlement_operation_allowed checks the requested operation against the active mode before any dispatch, release, or refund is permitted. An operator can freeze new dispatches while still allowing refunds, or halt the rail entirely, without touching signed receipt truth.


See Also