EconomyFindings
Pricing a Finding
How a buyer bounds its bid, how a seller posts a price, and how collateral and audits size the cost of fraud.
Pricing boundary
A finding's value to a buyer is a counterfactual the buyer cannot compute: P(would have attempted) x cost-if-attempted x P(would have hit the same dead end) x redundancy-across-siblings x decay. No mechanism on this page computes it. The market prices the buyer's outside option instead: what it would cost that buyer to re-derive the same result, discounted for how likely it was to try, how much a sibling finding already covers, and how strong the seller's guarantee is.
Re-derivation is a meterable action, so the buyer can build the estimate from its own recent metering history or a fresh quote for the same context and recipe. That estimate stays buyer-local policy. The shipped MeteredBillingQuote rides on GovernedTransactionIntent.metered_billing as caller-carried data, with no issuer signature and no binding to a finding context or replay recipe; the kernel checks its shape, time, and currency consistency and does not authenticate the named provider or how the number was derived. It therefore cannot establish a market-wide or operator-verifiable substitute price. The resulting clearing band is 0 < price <= buyer_local_ceiling: a posted price above a buyer's ceiling does not clear for that buyer. Production cost supplies no floor. It is sunk, and marginal delivery cost is near zero, so a seller recovers cost only when enough buyers' private ceilings sit above its ask.
The buyer-local bid ceiling
finding_bid_ceiling() in crates/economy/chio-open-market/src/finding_bid_policy.rs is the reference helper, mirrored by the TypeScript and Python SDKs against shared golden vectors. It takes one FindingBidCeilingInput, which nests the buyer's estimate and the buyer's own discount policy. Every integer field is a canonical decimal string, and every struct carries deny_unknown_fields and camelCase serde names.
/// One buyer-carried estimate of the cost of re-deriving a finding.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct BuyerFindingEstimate {
pub units: String,
pub currency: String,
pub provenance: String,
pub source_sha256: String,
pub context_sha256: String,
pub replay_recipe_sha256: String,
pub observed_at_unix_ms: String,
pub valid_until_unix_ms: String,
}
/// Buyer-owned discount and remaining-budget policy.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct FindingBidCeilingPolicy {
pub budget_remaining_units: String,
pub currency: String,
pub would_have_run_bps: String,
pub sibling_redundancy_bps: String,
pub guarantee_class_bps: String,
}
/// Complete input to [`finding_bid_ceiling`].
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct FindingBidCeilingInput {
pub estimate: BuyerFindingEstimate,
pub policy: FindingBidCeilingPolicy,
pub expected_source_sha256: String,
pub expected_context_sha256: String,
pub expected_replay_recipe_sha256: String,
pub now_unix_ms: String,
}The three expected_* digests and now_unix_ms sit beside the estimate so the helper can check the estimate against what the buyer actually intends to buy. Amounts and timestamps are bounded to Rust u64; each basis-point value is bounded to 0..=10_000. The discount multiplies with checked u128 intermediates and rounds down exactly once, floor(estimate * would_run * (10000 - redundancy) * guarantee / 10000^3), and the returned decimal string is then capped at policy.budget_remaining_units. The ceiling rises monotonically with the estimate, and a larger sibling_redundancy_bps lowers it. The function bounds a bid; it does not value the finding.
When the helper refuses
FindingBidCeilingError is fail-closed: the helper returns a ceiling or a named reason, never a best effort. Seven reasons name a semantic mismatch between the estimate and the purchase the buyer is pricing.
| Rejection | Condition |
|---|---|
CurrencyMismatch | The estimate currency and the budget currency differ, or either is not an uppercase alphanumeric code of at most sixteen bytes. |
ProvenanceUnsupported | estimate.provenance is neither buyer_metering_history_v1 nor buyer_fresh_metered_quote_v1. Both labels stay caller-carried and unsigned. |
SourceSubstituted | estimate.source_sha256 does not equal expected_source_sha256. |
ContextSubstituted | estimate.context_sha256 does not equal expected_context_sha256. |
ReplayRecipeSubstituted | estimate.replay_recipe_sha256 does not equal expected_replay_recipe_sha256. |
InvalidValidityWindow | observed_at_unix_ms is at or after valid_until_unix_ms. |
StaleEstimate | now_unix_ms falls before the observation instant or at or after the expiry instant. |
The remaining reasons guard the encoding rather than the semantics: InvalidDecimal for a value that is not a canonical unsigned decimal integer, U64Overflow for one past the u64 boundary, BasisPointsOutOfRange above 10_000, DigestMalformed for a digest that is not canonical lowercase 64-hex, and IntermediateOverflow for a wide product that leaves u128. Each of the first four names the offending field.
A worked vector
The shared golden vectors fix the cross-language answer. The first applies all three discounts to a 4200-unit estimate and expects 1890: the estimate keeps sixty percent for wouldHaveRunBps, then seventy-five percent for siblingRedundancyBps, then the full multiplier for a deterministic_replay class.
{
"id": "basic_discount",
"input": {
"estimate": {
"units": "4200",
"currency": "USD",
"provenance": "buyer_metering_history_v1",
"sourceSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"contextSha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"replayRecipeSha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"observedAtUnixMs": "1700000000000",
"validUntilUnixMs": "1700000060000"
},
"policy": {
"budgetRemainingUnits": "10000",
"currency": "USD",
"wouldHaveRunBps": "6000",
"siblingRedundancyBps": "2500",
"guaranteeClassBps": "10000"
},
"expectedSourceSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"expectedContextSha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"expectedReplayRecipeSha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"nowUnixMs": "1700000001000"
},
"expectedCeiling": "1890"
},Seller pricing
The ceiling bounds the buyer. The seller side is a unilateral posted price on the signed pricing hint, ListingPricingHint.price_per_call, set at publish time. The marketplace compares the buyer's max_price_per_call against that advertised price and refuses a bid below it with BiddingError::BidCeilingTooLow (crates/economy/chio-open-market/src/bidding.rs:389). Currency equality is checked first, and a mismatch is a separate refusal.
The signed BidRequest carries only max_price_per_call. It does not carry the estimate or the three multipliers, so an operator can audit that the submitted ceiling was enforced but cannot reconstruct why the buyer chose it. The estimate, would_have_run_bps, and sibling_redundancy_bps stay private planner policy. ADR-0017 lists no auction and no order book among its non-goals, and the marketplace has no counter-offer and no per-buyer price discrimination: sellers price against the demand signal already on the hint, recent_receipts_volume, which is provider-advertised and not independently proved.
Guarantee classes and how each prices
guarantee_class_bps reads off the three-class taxonomy every finding is sold under. Each class prices differently because each is re-checkable to a different degree.
| Guarantee class | Suggested bps | How it prices |
|---|---|---|
deterministic_replay | 10000 | Re-checkable by running the committed recipe. Priced at the full multiplier, with no discount for guarantee strength. |
metered_attested | 5000 | Execution, cost, and digest are attested, and claim semantics are not independently re-checkable. The discount is the buyer's self-insurance against honest-cost fabrication: a seller can meter a run truthfully and still be wrong about what the run proves. |
asserted | 500 | Seller-asserted, backed by the bond alone. Heavily discounted, and never silently upgraded to a stronger class. |
These multipliers are suggested policy defaults, not kernel constants, and an operator can retune all three per namespace. They parallel the existing reputation-tier discount idiom, TIER_DISCOUNT_PER_HUNDRED in crates/economy/chio-appraisal/src/marketplace_pricing.rs. The rule that does not bend: an asserted claim starts and stays asserted until independently re-verified. That is the same never-upgrade discipline property P10 carries for status reporting, whose Lean obligations are report_truthfulness_asserted_not_verified and report_truthfulness_observed_not_verified.
Honesty economics
Fraud is priced through the challenge lane, not through a market-only abuse class. An upheld finding challenge maps to the frozen v1 abuse class OpenMarketAbuseClass::FraudulentListing, one of the four OpenMarketAbuseClass variants, alongside SpamPublication, ReplayPublication, and UnverifiableListingBehavior. The finding-aware wrapper asserts that class before any penalty evaluation runs (crates/economy/chio-open-market/src/finding_penalty.rs:127), and the registered chio.registry.market-penalty.v1 record adds no field or enum of its own.
The penalty must carry exactly one external evidence reference whose reference_id equals the challenge outcome_id and whose sha256 equals the canonical signed-outcome envelope digest. A body-only digest, an absent digest, a generic or duplicated reference, a wrong abuse class, untyped evidence, and signer substitution each reject. A low reputation score or a disgruntled buyer's account of events opens nothing.
What a challenge may argue
chio finding challenge takes exactly one authorization branch and exactly one mechanical evidence class per filing. A buyer submission carries a dispute fee, a dispute bond, and standing, and is signed by the challenger it names; a venue audit carries none of those and is signed by the venue's pinned audit authority. The --class flag accepts three values, and the closed guarantee and evidence compatibility matrix is checked against the fetched finding before anything is signed.
| Class | What it argues, and what it requires of the finding |
|---|---|
digest-mismatch | The delivered content did not match the digest the buyer priced. Admits any guarantee and evidence class, because its standing is the signed failed-delivery terminal. An upheld verdict requires the committed and delivered digests to differ. |
evidence-invalid | A contested receipt fails re-verification. Requires an observed or verified evidence class. Only affirmative invalidity upholds; a resolved and valid subset rejects, and unavailable inputs are indeterminate. |
replay-contradiction | A re-run of the committed recipe contradicts the claim. Requires deterministic_replay and verified. The facet result maps onto the verdict directly. |
Every other guarantee and evidence pairing rejects before evaluation. The verdict is exactly upheld, rejected, or indeterminate, and only upheld may enter the penalty lane. An indeterminate outcome creates no hold, sanction, liability transition, audit reward, or forfeiture.
Collateral and exposure
A bond requirement on the fee schedule declares a class, amount, currency, and slashable bit. It is not live collateral. Admission resolves an unspent seller-collateral allocation from a trusted bond authority and binds it to the seller key, listing id, finding id, schedule requirement and version, class, currency, amount, and expiry; stale, wrong-owner, wrong-currency, and already-allocated collateral reject.
Because revenue can finalize before a challenge, admission and purchase atomically reserve encumbrance_per_sale = k * accepted_price with k >= 1, and enforce base_finding_stake + sum(open_encumbrances) <= min(locked_amount - slashed_amount, listing_requirement.required_amount) together with sum(open_encumbrances) <= maximum_sale_exposure, in checked arithmetic and exact currency. Exposure counts concurrent accepted or finalized sales inside the detection horizon and falls only when that predeclared horizon closes without an actionable event. This is a hard concurrency-safe cap. It replaces the earlier expectation bond >= k x price x expected_sales, which leaves an uncovered tail.
The slash amount follows from that arithmetic rather than from adjudicator discretion. An upheld outcome carries a checked penalty calculation recording the base stake, the open per-sale encumbrances, the computed exposure, the signed listing requirement, and the live allocated collateral. The amount equals min(live_allocated_collateral, computed_exposure), where computed_exposure = base + encumbrances, and an exposure above the signed requirement rejects rather than clamps. The penalty evaluator refuses a SlashBond whose amount exceeds the configured bond requirement with PenaltyAmountExceedsBond, and refuses it outright when the selected requirement is not slashable.
Slash proceeds go to harmed buyers pro rata by purchase amount, with any remainder to the registered community fund. validate_bond_impair_distribution enforces the exact sum, and contracts/src/ChioBondVault.sol repeats the cap and exact-sum check on chain. Challenger rewards, audit costs, operator fees, and adjudicator fees never come from the seller slash. The contract checks distribution shape, beneficiary count, amount bounds, and exact-sum shares; it does not itself recognize harmed buyers or the community fund, so the settlement operator derives those destinations from frozen purchase records and pre-sale market terms pin the community-fund identity.
Reversal is not restitution
ReverseSlash preserves the penalty state-machine path on a successful appeal. It does not retrieve funds an impairment transaction already distributed. The target profile therefore blocks impairment until finality; an appeal permitted after distribution needs a separately funded, receipt-backed restitution terminal. A state transition alone does not restore the seller's money.Probabilistic audits
A buyer challenge catches a fabrication somebody already bought. The venue closes that gap by auditing listed deterministic_replay findings at random, running the committed recipe against the bondless venue-audit branch. The deterrence condition is sized per listing class:
audit_rate x slash_amount >= expected_fabrication_profitwhere expected_fabrication_profit ~= price x expected_sales_in_window. Below that line, fabricating carries positive expected value and the audit budget under-funds its own deterrent. A published rate alone does not carry the property. Each audit epoch has to publish the eligible-listing snapshot, the class-specific rate, the deterministic selection algorithm, and a committed randomness source the venue cannot choose after seeing the snapshot; signed selection, attempt, completion, and missed-deadline receipts then let anyone recompute the sample and detect an omitted selected listing. That scheduler and its fee collection bound the claim: without them the condition sizes a target and enforces nothing.
Limited ground-truth re-execution is the mechanism because peer prediction does not substitute for it: under costly evaluation, mechanisms that reward agents for matching each other's reports admit low-effort and collusive equilibria. That is a narrowing, not an impossibility result. Peer and market signals may create an additional, separately disclosed risk-weighted sample, but they never alter the committed random sample and never settle an outcome.
Revenue timing
The settlement path observes a dispute window and holds no custody through it. ChioEscrow.releaseWithProofDetailed transfers funds on proof. chio-settle's finality inspection can label a transaction AwaitingDisputeWindow and cannot reverse it. The purchase chain uses only a short-lived pre-delivery reversible hold that captures immediately after a matched delivery, which is neither dispute-window custody nor a clawback. So seller revenue finalizes without a clawback route, and the collateral arithmetic above is what prices that. Holding revenue through a post-sale window would need new escrow semantics or a custody profile, which is a separate ADR decision.
A finding that was honestly derived and is simply wrong has no adjudication lane. None of the three challenge classes reaches it: there is no digest mismatch, no invalid evidence receipt, and, absent a deterministic_replay recipe, nothing to contradict. That risk is priced by the collateral, the guarantee-class discount, and reputation.
Next steps
- Paid Reveal · the digest-gated payout this ceiling and this collateral price
- Finding Revocation · what happens to a paid finding after a retraction
- Listing Disputes · the sanction and appeal lifecycle a
FraudulentListingcase runs through - Underwriting Risk Taxonomy · how a bond class and its requirements get sized
- Pricing Models ·
ListingPricingHintandMeteredBillingQuote, the metered-billing context this page builds on