EconomyCost & Settlementnew
Predeclared Settlement
Each escrow, bond, and claim fixes its release and refund outcomes at open time, including the amount and payee rules.
Use this page when
Implementation references
ChioEscrow and ChioBondVault (Solidity) and in chio-market (the Rust claim, adjudication, payout, and settlement records).The JELLY Incident, and the Invariant It Forced
On 2025-03-26 Hyperliquid delisted the JELLY (JELLYJELLY) perpetual after its HLP vault was squeezed in a roughly $13.5M tussle. Rather than let the position settle at the prevailing market mark, validators intervened at their discretion and force-settled the disputed market at the attacker's entry price. That single discretionary re-pricing flipped a roughly $13.5M vault loss into a reported $700k protocol profit, and drew “FTX 2.0” criticism.
The failure had three parts. Chio addresses each one in the settlement rules:
| JELLY failure part | What happened | Chio structural counter |
|---|---|---|
| Discretion | A privileged quorum chose, after the fact, to close a live market that no predeclared rule required closing. | Terminal outcomes are fixed at createEscrow time. A circuit breaker fires only if its trigger was enumerated ex ante (D3). |
| Re-pricing | The forced-close price was selected (the attacker's entry price) rather than derived from a committed, evidenced value. | Amounts are evidenced and monotone non-increasing (coverage >= claim >= award >= settlement). Chio proves an amount, it never selects one. |
| Self-dealing direction | The chosen price moved value toward the protocol treasury, converting a counterparty loss into protocol profit. | Destinations are limited to the harmed counterparty or a pre-registered community fund. A protocol or insider payee is rejected at validation. |
Chio's answer is one sentence: Chio never chooses a price, it proves one. Every terminal outcome, and every amount inside it, is committed before the dispute exists and is bounded above by what was deposited or covered.
Outcomes Fixed at Open Time
Every escrow has exactly two predeclared terminal outcomes, both fixed at createEscrow (or createEscrowWithPermit) time, and neither of which selects a price:
- Release. The pre-named beneficiary is paid the amount proven by a signed receipt (Merkle inclusion against an operator-signed root, or an operator settlement-key signature), capped at the deposit.
- Refund. After the committed
deadline, the unspent remainder returns to the depositor.
There is no third “forced settlement at a chosen price” state. The escrow terms (beneficiary, token, maxAmount, deadline, operator) are set at open, the escrow id is a deterministic hash of those terms, and a depositor funds only its own escrow.
The release entrypoints (releaseWithProofDetailed, releaseWithSignature, partialReleaseWithProofDetailed) route only to escrow.terms.beneficiary via _requireBeneficiary, run only while the escrow is live via _ensureLive, and cap the amount at the deposit via _ensureReleaseAmount. The non-detailed releaseWithProof and partialReleaseWithProof entrypoints revert ProofMetadataRequired, so a release without proof metadata fails closed rather than settling on a thinner record. refund is callable only after deadline and returns deposited - released to the depositor.
Open Time Fixes Both Branches
Circuit Breakers Are Enumerated Ex Ante or They Do Not Fire
If Chio ever needs an early-closure circuit breaker (operator-key compromise, a frozen or forked root registry, a sanctioned counterparty), its triggering condition, routing, and amount rule must all be written into contract code and into ADR-0015 before it can fire. A breaker decided after the triggering event, by a human or a quorum, is prohibited. Absence of a predeclared breaker does not create discretion: the escrow simply runs to its release-or-refund terminal states, never closed ad hoc.
The Monotone Non-Increasing Amount Chain
The Chio analog of a “settlement price” is an evidenced amount (settledAmount, awarded_amount, settlement_amount), never a quoted or after-the-fact mark. Each such amount is monotone non-increasing down the chain, coverage >= claim >= award >= settlement, and each step is backed by a signed record:
BoundPolicy::file_claimcaps the payout at the coverage limit (requested.min(coverage_limit)), so coverage >= claim holds by construction.LiabilityClaimAdjudicationArtifactenforces that the award never exceeds the claim, and that apartial_settlementaward is strictly less than the claim, so claim >= award.LiabilityClaimPayoutInstructionArtifactmatchespayout_amountto the adjudicated award, andLiabilityClaimSettlementInstructionArtifactholdssettlement_amountat or belowpayout_amount, so award >= settlement.
A single claim, viewed as its amount chain (illustrative, not a signed wire schema, amounts in USD minor units):
{
"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
}The chain can only shrink: 30,000 covered, 25,000 claimed, 22,500 awarded, 20,000 settled downstream. No step can raise the number or point the payee at the protocol. JELLY's two harms, re-pricing and self-dealing direction, become arithmetic and payee constraints rather than good behavior.
No Self-Dealing: Fixed Destinations and a Predeclared Roster
A predeclared breaker may only route an already-committed, evidenced amount to a predeclared destination. The permitted destinations are exhausted by two:
- the harmed counterparty (the depositor, the bond principal, or the coverage beneficiary or subject of record), or
- a registered community fund address anchored ex ante (for example in
ChioRootRegistry).
A settlement or slash that would send value to the protocol treasury, an operator wallet, an insider, or any address outside that set is rejected at validation time. No closure may set an amount that converts a counterparty loss into protocol or insider gain: this is the structural form of invariants 9 and 10. The comptroller's market_slash lane is the reference implementation. It forces the payee to be the coverage beneficiary_subject (or the coverage subject), never the protocol, and caps each slash by a signed sanction authority with a predeclared maximum_slash_units.
Adjudication Chooses Among Fixed Outcomes, from a Predeclared Roster
Liability-claim adjudication is a choice among the predeclared outcomes (claim_upheld, provider_upheld, partial_settlement) inside the amount envelope above. It is not a lane for inventing a novel price or a novel payee. Follow-up B (accepted, Rust value path) makes the adjudicator itself checkable: LiabilityClaimAdjudicationArtifact carries two signature-safe fields:
decision_rule_ref: the id of the predeclared decision rule (or circuit-breaker condition) the adjudicator applied.roster_anchor_ref: the id or hash of the signed roster record used to check the adjudicator.
A validate_against_roster policy gate enforces roster membership, an allowed decision-rule set, and that the recorded roster_anchor_ref equals the anchor of the roster actually applied. Every value-path constructor (adjudication, payout instruction, settlement instruction) is a fail-closed choke point that must call this gate, and a CI check rejects any liability value-path record constructed without it.
// Follow-up B additions to the adjudication record (accepted, Rust value path).
// Outcome set and amount envelope are unchanged: award <= claim,
// and a partial_settlement award is strictly less than the claim.
pub struct LiabilityClaimAdjudicationArtifact {
// ... claim ref, outcome (claim_upheld | provider_upheld | partial_settlement),
// awarded_amount, signatures ...
pub adjudicator: String,
pub decision_rule_ref: Option<String>, // predeclared decision rule / circuit-breaker id applied
pub roster_anchor_ref: Option<String>, // anchor of the signed adjudicator roster checked against
}
// validate_against_roster (policy gate). Every value-path constructor
// (adjudication, payout instruction, settlement instruction) MUST call it:
// 1. adjudicator is a member of the anchored roster
// 2. decision_rule_ref is in the allowed decision-rule set
// 3. roster_anchor_ref == anchor of the roster actually applied
// A CI check rejects any liability value-path record built without this gate.The Honest Boundary: Pause Exists, Re-Pricing Does Not
ADR-0015 is explicit that the guarantee is narrower than “no admin at all.” The value-movement contracts (ChioEscrow, ChioBondVault) each carry a transferable admin, a token allowlist, and a pause flag. What that admin cannot do is the JELLY move: it cannot directly transfer escrowed or bonded funds, choose a settlement amount, change a payee, or upgrade the contracts.
What it can do is pause. Pause blocks escrow creation and every release entrypoint, plus bond lock, release, and impairment, while post-deadline escrow refund and bond expireRelease remain callable. So the admin can delay a beneficiary or a slash path, and can cause the predeclared refund or expiry branch to win. That is a real discretionary liveness risk: it changes which of the two predeclared outcomes occurs, it never invents a new one, and it never re-prices.
Two risks remain:
- Bond slash destinations (follow-up A, deferred).
ChioBondVault.impairBondDetailedis evidence-gated (Merkle proof against an operator-signed root), operator-only, bounded by the remaininglockedAmount, and requiressum(shares) == slashAmountexactly. But thebeneficiaries[]set is chosen by the operator at call time, and nothing on chain yet constrains it to the harmed party or the registered community fund. The Rustmarket_slashlane already enforces that constraint off chain; pushing it into the contract is a new deployment, so it stays deferred. - Adjacent admin controls.
ChioIdentityRegistrycandeactivateOperatorandChioPriceResolvercan set prices. Neither can move escrowed or bonded funds, so neither is a JELLY lane on its own, but operator deactivation and price-feed administration are where upstream discretion could indirectly starve or mis-value a settlement. They sit outside the D1 to D4 guarantees, called out so a future change cannot quietly turn one into a back door.
The honest cost: Chio cannot make a harmed party whole by fiat after an incident. If a counterparty is hurt by something outside the predeclared breakers, the remedy is a future predeclared breaker plus off-chain restitution, not an emergency on-chain re-route. That is the intended price of being un-JELLY-able.
Devnet limits
See Also
- On-Chain Settlement for the escrow contracts, the two release paths, and the nine-state lifecycle that governs this design.
- Claims Lifecycle for the claim, response, dispute, adjudication, payout, and settlement record chain that carries the amount envelope.
- Liability and Insurance Market for the coverage binding that sets the top of the amount chain.
- Credit Facilities and Bonds for the bond vault and the loss lifecycle a slash draws against.
- Authoritative Spend for how a receipt is judged to represent real, mediated spend in the first place.