Chio/Docs
LOGIN · JOIN

On-Chain Settlement

See how an escrow funded for one call releases against its signed receipt, and how the observer classifies what the chain did.

Concept chio@5f63e6e

On this page

A deposit locked in ChioEscrow pays its beneficiary only against evidence from the kernel: an operator signature over the receipt, or a proof that the receipt sits under a published checkpoint root.

Chio prepares each transaction; a wallet signs and submits it, and the settlement observer projects what the chain did into a lifecycle state. The web3 module is off by default, and a deployment turns it on to settle on chain. The grant's holds and caps still prevent spend before dispatch, and on-chain outcomes are observed and recorded.

A release carries one of two kinds of evidence

The dispatch picks its path in Web3SettlementPath before any release is prepared: DualSignature or MerkleProof. One escrow contract accepts both, so an operator can run some flows on each at the same address.

Escrow releaseChoose a path.

Opening fixes both branches

Opening the escrow fixes the beneficiary, the token, the maximum amount, and the deadline. The depositor funds its own escrow, and those terms decide where a release and a refund can go. Predeclared settlement.

The EVM escrow release path: the terms fixed at opening, the two evidence paths a release accepts, and the refund after the deadline. Chain execution and finality are observed; signed receipts and the pinned verifier policy stay the authority.Settlement

Opening fixes the beneficiary, the token, the maximum amount, and the deadline. Under DualSignature, prepare_dual_sign_release verifies the receipt, reads the operator registry at a pinned block, and signs the EIP-712 release digest with the registered operator settlement key. The beneficiary submits releaseWithSignature, and the contract checks the caller, the current operator key and epoch, the full remaining amount, and that the receipt is unused.

No buyer countersignature is involved, so this path fits when the registered operator signer is available and the release pays the full settlement amount.

Under MerkleProof, prepare_merkle_release binds the receipt to an AnchorInclusionProof under a checkpoint root registered in ChioRootRegistry, with a SettlementAnchorContentBinding and the execution amount. Each helper rejects a dispatch configured for the other path, so a lost operator signer is an interruption to resolve under the selected path rather than a switch to a proof.

Read more in Predeclared Settlement, which checks the amount and destination constraints fixed at opening.

A 1.50 USDC test escrow releases on an operator signature

This run uses 1.50 test USDC on Base Sepolia, with the capability bound to the Web3 rail and the DualSignature path.

  1. Dispatch. The kernel signs a capital-execution instruction for 1.50 USDC, and prepare_web3_escrow_dispatch builds a PreparedEscrowCreate.
  2. Lock. The operator's signer broadcasts the dispatch transaction, and the escrow locks 1.50 USDC in state EscrowLocked.
  3. Run. The tool runs, and the observed cost matches the quoted 1.50 USDC.
  4. Sign. prepare_dual_sign_release signs the release digest. The observed amount must equal the dispatch's full settlement amount.
  5. Release. The beneficiary submits the prepared releaseWithSignature call, and the observer waits for the required finality before projecting Settled.

The MerkleProof variant replaces the signing step. Publish the checkpoint root through the configured anchor and retain the receipt's inclusion proof, call prepare_merkle_release, and submit the prepared call through the authorized account. Checkpoint publication, transaction inclusion, and finality each take time, and an unavailable proof blocks release preparation.

A prepared call becomes payment only after submission and finality

Chio builds each dispatch and release as a PreparedEvmCall, with from_address, to_address, data, and an optional gas limit, ready for an external signer to sign and broadcast.

Rails outside the kernelChoose a moment.

Rail outcomes are observed and recorded

The rail reports RailSettlementStatus, which folds into the receipt’s SettlementStatus: NotApplicable, Pending, Settled, or Failed. The kernel records the outcome and the payment_reference on the signed receipt; it does not decide what the rail did. What each receipt records.

Payment rails as optional modules attached to the kernel through the PaymentAdapter lifecycle. Holds and caps prevent spend before dispatch; what the rail does is observed and recorded. The modules are off in default builds; custody and the facilitator service are left out.Settlement rails

The release digest and the transaction have separate signers. The DualSignature helper takes the operator settlement private key as input and signs the digest; the beneficiary's wallet or signer service then signs and submits the transaction. The host controls both signing operations and keeps private keys out of receipts and exported evidence.

Reconciliation works from the submitted transaction's identity, the observed escrow state, and the original dispatch, because a prepared signature establishes neither inclusion nor finality. EVM preparation sets real_dispatch_supported in each dispatch's support boundary, and validation refuses a dispatch that leaves it false.

Read more in Integrations / Settlement for chain-by-chain configuration and finality details.

The observer projects one state from finality and the escrow snapshot

Web3SettlementLifecycleState has nine variants. The observer reaches six of them by testing finality first and the snapshot second, and the first matching case wins.

Escrow projectionChoose a state.

A full release reads as settled

Every test passes through: the release is final, nothing was refunded, and the full deposit reached the beneficiary. The projection is Settled and suggests no action. Reconciliation.

The projection chio-settle applies to one EVM escrow: finality is tested first, then the snapshot's refund flag and released amount, and the first matching case names the state and the recovery action it suggests. A projection records evidence; a release, retry, or refund is a separate submitted transaction. The three states the observer never projects are left out.

A reorg projects Reorged, and any other unfinalized observation projects EscrowLocked, whatever the snapshot says. Once the observation is final, a refunded snapshot projects TimedOut, which an elapsed clock alone never produces. Nothing released projects Failed, less than the deposit projects PartiallySettled, and the full deposit projects Settled.

The other three variants are kernel-side records. PendingDispatch means a signed dispatch exists and no transaction has been observed. Reversed and ChargedBack record a reversal or an off-chain dispute after the contract reached one of its two predeclared, price-free terminal outcomes: release on proof, or refund after the deadline. An admin pause stops new escrows and releases, and both exits keep the amount and destination constraints fixed at opening.

Recovery starts from what the chain shows

SettlementFinalityAssessment measures each transaction against its chain's required confirmation count and dispute window in seconds. Each deployment records a Web3FinalityMode (OptimisticL2, L1Finalized, or SolanaConfirmed) with a minimum confirmation count.

The status is awaiting_confirmations while a mined transaction is short of the required depth, awaiting_dispute_window while it is confirmed inside an open optimistic challenge window, finalized once both are satisfied, and reorged when a confirmed transaction leaves the canonical chain. The observer attaches a SettlementRecoveryAction to the projection: WaitForConfirmations or WaitForDisputeWindow short of finality, ResubmitAfterReorg after a reorg, RetrySubmission for a finalized Failed, and ExecuteRefund for TimedOut. The enum's other two variants, ManualReview and ExpireBond, serve the bond-vault lifecycle. The host executes and observes any action it selects.

  • Invalid operator key, epoch, or signature. Resolve the registry or key mismatch and prepare again under the selected path; a buyer signature is never a substitute. The issue closes with a valid prepared call and its successful execution.
  • Missing proof or root. Obtain the bound inclusion proof and the registered root, and keep the escrow pending until the contract accepts the proof and the release reaches the required finality.
  • Lost submission response. Query the submitted transaction and the escrow before deciding whether another submission is needed, because a transport timeout proves neither success nor failure.
  • Reorged release. Re-evaluate the escrow from the finality observation and take the resubmission action that applies, until a canonical, sufficiently confirmed observation exists.
  • Deadline passed with value remaining. Read the live escrow, submit the explicit refund when it is eligible, and observe the refunded state and its finality. A recovery action is a classification; only a submitted transaction moves funds.

Read more in Reconciliation, which closes partially settled and timed-out escrows against their original records.

On-chain settlement reference

Contract families

The contract registry classifies five interface families as Web3ContractKind in chio-web3. Chain-specific addresses live in each chain's Web3ChainDeployment; check support for the selected deployment. Bindings ship as Rust types in chio-web3-bindings, with Solidity ABIs versioned alongside the kernel, and the chio-settle EVM module drives the contracts and records on-chain state in the receipt records.

ChioRootRegistry

Anchors the checkpoint roots the kernel publishes. Every Merkle release verifies a leaf against a root already registered here.

ChioEscrow

Locks funds against a capability commitment and holds the dispatch reference, the agreed amount, and the lifecycle state. It settles by dual signature or Merkle proof and refunds explicitly after the opening deadline; the contract source shows the beneficiary checks, release bounds, and refund entrypoint. Payment Channels build on the same contract: 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.

ChioBondVault

Holds bonds, operator collateral and agent collateral, that back high-trust capabilities. A bond is released, expired, or impaired against a slashing event.

ChioIdentityRegistry

Binds Chio public keys to on-chain settlement addresses. The contract checks that the binding an operator presents has the correct purpose (settle or publish) and chain scope.

ChioPriceResolver

Returns FX prices from the configured oracle when a receipt is denominated in a non-native asset. The escrow uses it on release to compute the settlement amount in the chain's settlement token.

Settlement path and lifecycle enums

crates/economy/chio-web3/src/trust_profile.rsrust
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Web3SettlementPath {
    DualSignature,
    MerkleProof,
}
crates/economy/chio-web3/src/settlement.rsrust
#[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,
}
  • pending_dispatch: a signed dispatch record exists; no on-chain transaction has been observed.
  • escrow_locked: funds are in ChioEscrow, awaiting finality or release.
  • partially_settled: a partial release has paid out and the remainder is still locked.
  • settled: the release executed, the funds reached the beneficiary, and finality is confirmed.
  • reversed: a reversal record in the wider lifecycle vocabulary; the EVM observer projects a finalized refunded escrow as timed_out.
  • charged_back: a post-settlement reversal recording an off-chain dispute clawback, after the contract reached its terminal outcome.
  • timed_out: finality is established and the escrow snapshot is marked refunded.
  • failed: the finalized snapshot has no released amount and is unrefunded; inspect the execution evidence before retrying.
  • reorged: a confirmed settlement was undone by a chain reorganization and needs resubmission.

EVM entry points and deployments

The chio-settle EVM module splits into mod.rs, types.rs (the Prepared* request and response types), prepare.rs (the prepare_* constructors), and finalize.rs (the confirm and finality helpers).

  • prepare_web3_escrow_dispatch: builds a PreparedEscrowCreate from a signed capital-execution instruction.
  • prepare_dual_sign_release: builds a PreparedDualSignRelease with the EIP-712 digest signed by the operator key.
  • prepare_merkle_release: builds a PreparedMerkleRelease carrying the receipt leaf hash, the root, and the proof path.
  • prepare_escrow_refund: builds the explicit refund call after the opening deadline. The refund entrypoint stays callable while the contract is paused, and its deadline and already-refunded checks still apply.
  • prepare_bond_lock, prepare_bond_release, prepare_bond_impair: drive ChioBondVault through its lifecycle.
  • prepare_erc20_approval: emits the ERC-20 approve() call the escrow needs before it can pull tokens.

The shipped deployment templates target 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. chio-web3 names Base as the primary chain and Arbitrum, Ethereum, Optimism, Polygon, Linea, BSC, Avalanche, and zkSync beside it, with Base Sepolia as the public testnet. A mainnet deployment is promoted from a reviewed manifest derived from its template, under an approval artifact that binds the manifest hash, and promotion passes the mainnet cutover checklist: an independent external audit with no unresolved critical or high findings, a four-week testnet soak, artifact digest and runtime codehash gates, the minimum-threshold checks, and security-owner sign-off. Local devnet, runtime devnet, and the Base Sepolia public testnet are the rehearsal environments, and local qualification reports or prior contract reviews never count as promotion approval.

Solana preparation and verification

Solana support covers local verification and instruction preparation: an external submitter broadcasts, chio-settle runs no on-chain Solana program and keeps no cluster index, and no escrow contract holds 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.

crates/economy/chio-settle/src/solana.rsrust
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 submitter assembles the transaction that pairs the native Ed25519 signature check with the SPL token transfer. Before the dispatch is prepared, verify_solana_binding_and_receipt confirms that the binding has the settle purpose, that its chain scope covers the target chain, and that the settlement address decodes as a valid base58 Solana address. compare_commitments reconciles the prepared commitment against the observed one and reports a CommitmentConsistencyReport for parity checks.

Cross-chain messages over Chainlink CCIP

A settlement can span chains, for example settled on Base after the depositor funded the escrow from Arbitrum. The CCIP message envelope in chio-settle is a typed coordination layer over Chainlink's Cross-Chain Interoperability Protocol that lets a settlement event on one chain be reconciled with state on another; it moves no funds itself.

crates/economy/chio-settle/src/ccip.rs23-30rust
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,
}

A prepared message carries one of five statuses:

crates/economy/chio-settle/src/ccip.rs13-19rust
pub enum CcipMessageStatus {
    Prepared,
    Reconciled,
    DuplicateSuppressed,
    Delayed,
    Unsupported,
}

prepare_ccip_settlement_message validates the lane (source and destination differ, payload bounds are nonzero, and the validity window is at least twice the expected latency), then assembles a payload with the dispatch id, execution receipt id, settlement reference, lifecycle state, settled amount, and beneficiary address. reconcile_ccip_delivery compares the SHA-256 digest of the delivered payload with the digest the kernel signed. Use CCIP when:

  • The escrow chain and the bond vault chain differ, such as an operator on Ethereum with escrow on Base.
  • A multi-chain operator needs one settlement event delivered to several treasury locations.
  • The integration partner already speaks CCIP and will not accept a bespoke bridge.

For a single-chain flow, plain EVM dispatch on that chain is simpler and cheaper. Chainlink Oracles covers the full Chainlink integration.

Checkpoint anchoring

A Merkle release depends on the root it verifies against. chio-anchor publishes batched checkpoints as signed Web3CheckpointStatement records carrying checkpoint_seq, batch_start_seq, batch_end_seq, tree_size, the Merkle root, the kernel public key, and the signature, to the ChioRootRegistry on each target chain. A regulator, auditor, or dispute resolver can then check an inclusion proof from the chain-registered root and the receipt's leaf hash, under the admitted root publication authority and the configured contract and finality checks.

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

The same checkpoint can be anchored by several methods for defense in depth, and proof-bundle verification fails closed: verify_proof_bundle rejects the whole bundle if any one lane is bad, and verify_proof_bundle_with_discovery adds freshness checks. The receipt-side proof record is Web3ReceiptInclusion, with checkpoint_seq, merkle_root, and the proof path. verify_anchor_inclusion_proof in the chio-web3 anchors module is the authoritative verifier, and both record types are re-exported through chio-anchor. Receipts lists the receipt fields that enter Merkle inclusion.

Read more in Anchoring, and see escrow that pays on a verifier's decision in Work Claim Escrow.

Payment helpers and emergency modes

Beside the escrow lifecycle, the chio-settle payments module prepares account-level payment rails:

  • build_x402_payment_requirements: assembles an x402 HTTP 402 payment requirement.
  • prepare_transfer_with_authorization: builds an EIP-3009 transfer-with-authorization call.
  • evaluate_circle_nanopayment: evaluates a Circle nanopayment.
  • prepare_paymaster_compatibility: checks ERC-4337 paymaster compatibility.

The ops module gates settlement operations behind SettlementEmergencyMode, which has five states: Normal, DispatchPaused, RefundOnly, RecoveryOnly, and Halted. ensure_settlement_operation_allowed checks each dispatch, release, or refund against the active mode, so an operator can freeze new dispatches while still allowing refunds, or halt the rail entirely, and signed receipts stay as they were signed.

Next: retain a complete escrow evidence set

For one test escrow, retain the opening terms, the dispatch, the prepared call, the submitted transaction identity, the observed escrow state, and the finality record.