Chio/Docs
LOGIN · JOIN

Predeclared Settlement

Fix release conditions, refund destinations, and amount bounds when opening an escrow, bond, or claim.

Concept chio@5f63e6e

On this page

A buyer can read every way its money can leave an escrow before it funds one. Opening fixes the beneficiary, the refund destination, the maximum amount, and the deadline, and every later release, refund, award, or slash stays inside those terms.

Later transitions choose among outcomes the terms already name; none of them sets a price or a payee. The same rule runs through bonds and liability claims, where each signed step can only shrink the amount. The escrow and bond contracts belong to the optional web3 module and liability claims to the optional liability market, both off in default builds.

Opening an escrow fixes both of its endings

Every escrow has exactly two terminal outcomes, both fixed when createEscrow or createEscrowWithPermit runs.

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
  • Release. The named beneficiary receives the amount a signed receipt proves, by Merkle inclusion against an operator-signed root or by an operator settlement-key signature, capped at the deposit.
  • Refund. After the committed deadline, the unspent remainder returns to the depositor.

The terms (beneficiary, token, maxAmount, deadline, operator) are set at open, the escrow id is a deterministic hash of them, and a depositor funds only its own escrow. No third state settles at a chosen price.

Each release entrypoint (releaseWithProofDetailed, releaseWithSignature, partialReleaseWithProofDetailed) pays only escrow.terms.beneficiary through _requireBeneficiary, runs only while the escrow is live through _ensureLive, and caps the amount at the deposit through _ensureReleaseAmount. The non-detailed releaseWithProof and partialReleaseWithProof revert ProofMetadataRequired, so a release without proof metadata fails closed. refund runs only after deadline and returns deposited - released.

A deposit of 100 releases 85 and refunds 15

An escrow holds 100 token base units under fixed terms. A permitted partial proof release pays 85 for verified work, and the other 15 wait for a later eligible release or the refund.

  1. Create. 100 deposited; createEscrow validates and records the terms that fix the beneficiary and the depositor.
  2. Partial proof release. partialReleaseWithProofDetailed verifies the bound proof and pays 85 to the fixed beneficiary; 15 remain.
  3. Signature release. A signature release pays the full remaining amount, and the DualSignature preparation requires its full dispatch amount, so the 85-of-100 release takes the proof path.
  4. Refund after the deadline. refund is an explicit transaction that returns the unspent 15 to the depositor, followed by observation and finality.
  5. Operational pause. A pause changes when execution is available and leaves the price and the destination as written.

Retain the opening terms and the deposit evidence, prepare the proof release through the on-chain execution workflow, and retain each observed release and refund. A failed proof verification means the 85-unit release was never authorized. After a submission timeout, read the live escrow before you attempt another release.

Read more in ChioEscrow, which carries the partial proof, full signature, and refund branches.

A circuit breaker fires only if it was written down first

An early-closure breaker for operator-key compromise, a frozen or forked root registry, or a sanctioned counterparty fires only when its trigger, its routing, and its amount rule are already in contract code and in ADR-0015, the decision record that governs predeclared settlement. A breaker chosen after the event, by a person or a quorum, is prohibited. With no predeclared breaker, the escrow runs to release or refund.

A predeclared breaker may only route an amount that is already committed and evidenced, and only to a predeclared destination. Adding a breaker in a new contract leaves every existing escrow’s amount and destination constraints as they were.

The discretionary-settlement risks this design constrains

In its March 26, 2025 announcement, Hyperliquid said its validators voted to delist JELLY after suspicious market activity and that the Hyper Foundation would reimburse users apart from flagged addresses. It reported HLP’s 24-hour profit and loss as approximately 700,000 USDC, an interval figure that establishes neither an incident profit nor a transfer to a protocol treasury. The design concerns below are Chio’s own and make no forensic claim about that event.

  • Discretion. A privileged party closes a live agreement under a rule chosen after the dispute began. Chio fixes terminal outcomes at createEscrow and fires a breaker only when its trigger was enumerated beforehand.
  • Re-pricing. An operator-selected price replaces a disputed amount outside the agreement’s bounds. Chio’s amounts are evidenced and monotone non-increasing, and release verifies the evidenced amount within those bounds.
  • Self-dealing direction. An intervention sends value committed to a counterparty to a new protocol or insider destination. Chio limits destinations to the harmed counterparty or a pre-registered community fund and rejects any other payee at validation.

Each signed step can only shrink the amount

The settlement figure is an evidenced amount (settledAmount, awarded_amount, settlement_amount), never a quoted or after-the-fact mark. Down a liability claim the amounts obey coverage >= claim >= award >= settlement.

Amount chainChoose a case.

Each signed step can only shrink the amount

The claim is capped at the coverage limit, the award at the claim, and the settlement at the payout, which matches the award: USD 30,000 covered, 25,000 claimed, 22,500 awarded, 20,000 settled.

One liability claim’s amounts, coverage >= claim >= award >= settlement, with the signed record that holds each step, and the destinations the settled amount may reach. Amounts are illustrative; the response, dispute, and payout records are left out.
  • BoundPolicy::file_claim caps the payout at the coverage limit with requested.min(coverage_limit), so coverage covers the claim by construction.
  • LiabilityClaimAdjudicationArtifact keeps the award at or below the claim, and a partial_settlement award strictly below it.
  • LiabilityClaimPayoutInstructionArtifact matches payout_amount to the adjudicated award, and LiabilityClaimSettlementInstructionArtifact holds settlement_amount at or below payout_amount.

In the example claim, 30,000 is covered, 25,000 claimed, 22,500 awarded, and 20,000 settled. Amount bounds and permitted destinations are verification conditions on every signed transition, so no step can raise the number or name the protocol as payee.

The example claim as one record

A view of the chain in USD minor units, written for reading rather than as a signed wire schema:

claim-amount-chain.jsonjson
{
  "amount_chain": "coverage >= claim >= award >= settlement",
  "coverage_limit":    { "units": 3000000, "currency": "USD" },
  "claim_amount":      { "units": 2500000, "currency": "USD" },
  "awarded_amount":    { "units": 2250000, "currency": "USD" },
  "settlement_amount": { "units": 2000000, "currency": "USD" },
  "outcome": "partial_settlement",
  "destination": "coverage_beneficiary_subject",
  "protocol_is_payee": false
}

Value reaches only the harmed party or a registered fund

The permitted destinations are exactly two: the harmed counterparty (the depositor, the bond principal, or the coverage beneficiary or subject of record), or a community fund address registered ahead of time, for example in ChioRootRegistry. A settlement or slash that would pay the protocol treasury, an operator wallet, an insider, or any other address is rejected at validation.

No closure can set an amount that turns a counterparty’s loss into protocol or insider gain, the structural form of token invariants 9 (penalty proceeds never accrue to insiders) and 10 (no discretionary re-pricing or self-dealing). The comptroller’s market_slash lane is the reference implementation: it forces the payee to the coverage beneficiary_subject (or the coverage subject) and caps each slash by a signed sanction authority with a predeclared maximum_slash_units.

Bond slashes split that guarantee across two layers. ChioBondVault.impairBondDetailed is evidence-gated by a Merkle proof against an operator-signed root, callable only by the operator, bounded by the remaining lockedAmount, and requires sum(shares) == slashAmount. The vault accepts the beneficiaries[] the operator passes at call time; the market_slash lane that issues the call holds them to the harmed party or the registered fund. To check a slash destination, read the lane rather than the vault.

Adjudication picks a predeclared outcome from a predeclared roster

A liability-claim adjudication chooses among claim_upheld, provider_upheld, and partial_settlement, inside the amount envelope. LiabilityClaimAdjudicationArtifact makes the adjudicator checkable with two signature-safe fields: decision_rule_ref, the predeclared decision rule or breaker condition applied, and roster_anchor_ref, the id or hash of the signed roster record that admitted the adjudicator.

crates/economy/chio-market/src/claim.rs465-478rust
/// Fail-closed adjudication policy gate (ADR-0015).
///
/// Requires the adjudicator to be an exact (trimmed) member of the
/// operator-supplied predeclared `roster`, requires `decision_rule_ref` to
/// be present and a member of `allowed_decision_rules`, and requires the
/// recorded `roster_anchor_ref` to equal `roster_anchor` (the id/hash of the
/// signed roster artifact the `roster` was drawn from). Callers pass concrete
/// values so `chio-market` needs no dependency on the roster's source crate.
pub fn validate_against_roster(
    &self,
    roster: &[String],
    allowed_decision_rules: &[String],
    roster_anchor: &str,
) -> Result<(), MarketError> {

The validate_against_roster gate checks roster membership, an allowed decision-rule set, and that the recorded roster_anchor_ref equals the anchor of the roster applied. Every value-path constructor (adjudication, payout instruction, settlement instruction) calls it and fails closed. Callers pass the roster values directly, so chio-market needs no dependency on the roster’s source crate.

The adjudication record and its enforcement check
crates/economy/chio-market/src/claim.rs351-378rust
/// Adjudicator decision over a disputed claim, optionally recording the
/// predeclared decision rule and roster anchor it was checked against.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct LiabilityClaimAdjudicationArtifact {
    pub schema: String,
    pub adjudication_id: String,
    pub issued_at: u64,
    pub dispute: SignedLiabilityClaimDispute,
    pub adjudicator: String,
    pub outcome: LiabilityClaimAdjudicationOutcome,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub awarded_amount: Option<MonetaryAmount>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub note: Option<String>,
    /// Predeclared decision rule or circuit-breaker condition id the
    /// adjudication applied (ADR-0015). Optional and omitted when
    /// absent so existing signed fixtures keep byte-stable canonical JSON.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub decision_rule_ref: Option<String>,
    /// Id or hash of the signed roster artifact the adjudicator was checked
    /// against (ADR-0015 anchoring). Records which ex-ante roster
    /// was applied so the check is auditable and not per-adjudication fabricable.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub roster_anchor_ref: Option<String>,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub evidence_refs: Vec<LiabilityClaimEvidenceReference>,
}

Every Chio release passes the liability-roster-enforcement gate before it is tagged: it fails when any of the three value-path artifacts is constructed outside liability.rs, or when that file carries fewer than three validate_against_roster calls. chio release verify --evidence qualification shows its result for the release you run.

An admin can pause the contracts, and a pause never re-prices

The value path runs through the Solidity contracts ChioEscrow and ChioBondVault and the Rust claim, adjudication, payout, and settlement records in chio-market. Each contract carries a transferable admin, a token allowlist, and a pause flag. The admin has no path to transfer escrowed or bonded funds, choose a settlement amount, change a payee, or upgrade the contracts.

A pause blocks escrow creation and every release entrypoint, plus bond lock, release, and impairment. Post-deadline escrow refund and bond expireRelease stay callable. So an admin can delay a beneficiary or a slash path and make the refund or expiry branch win: a liveness risk that picks between the two predeclared outcomes, invents none, and never re-prices.

Two adjacent controls could starve or mis-value a settlement indirectly: ChioIdentityRegistry can deactivateOperator and ChioPriceResolver can set prices. Neither moves escrowed or bonded funds, and both sit outside the price and payee guarantees. Chain execution and finality are observed and recorded; the signed record supports the amount, and custody and availability rest with the chain and its operators.

Next: check the terms, then fund