From 87d04f0fdbfd14d5e05ce08f8578bf60f4b053ee Mon Sep 17 00:00:00 2001 From: Kayce10 Date: Fri, 28 Aug 2026 15:49:56 +0000 Subject: [PATCH 1/5] docs: add V2 bond sizing and window analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Models three v2-specific deployment decisions that were previously reasoned about only qualitatively in V2_RESOLUTION.md: - Default-frequency model: derives the minimum reveal turnout required for a strict-majority correction as a function of the honesty share of revealers, and shows that a lone disputer (W = 2B) can never by itself cross the strict-majority threshold. - Whale-capture model: computes the minimum capital required for a single address or coalition to reach strict majority as a function of base_bond, max_position, and expected honest counter-stake. Shows that max_position = 2 × base_bond prevents single-address capture with no counter-stake. - Window-length tradeoff model: frames registration and reveal durations, anti-snipe extension, and hard cap as a joint optimization over participation latency, coordination time, and capture speed. Provides sanity-check inequalities (T_rev ≥ 2τ_coord, T_reg ≥ τ_react, etc.). - Recommended profiles: private beta / public testnet / higher-value mainnet candidate, following the same three-tier structure as BOND_SIZING.md, with a numeric profile table and narrative per tier. - Scenario checks and monitoring guidance following the BOND_SIZING.md style. Closes #75 --- docs/src/SUMMARY.md | 1 + docs/src/V2_BOND_SIZING.md | 581 +++++++++++++++++++++++++++++++++++++ 2 files changed, 582 insertions(+) create mode 100644 docs/src/V2_BOND_SIZING.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index b144b72..7bd89b0 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -11,6 +11,7 @@ - [Deployment & Operations](DEPLOYMENT.md) - [Bond Sizing Analysis](BOND_SIZING.md) - [Deployment & Operations: Protocol v2](DEPLOYMENT_V2.md) + - [V2 Bond Sizing and Window Analysis](V2_BOND_SIZING.md) - [Integration Guide](INTEGRATION.md) - [v1/v2 Migration Runbook](V2_MIGRATION.md) - [Glossary](GLOSSARY.md) diff --git a/docs/src/V2_BOND_SIZING.md b/docs/src/V2_BOND_SIZING.md new file mode 100644 index 0000000..f65ccf4 --- /dev/null +++ b/docs/src/V2_BOND_SIZING.md @@ -0,0 +1,581 @@ +# V2 bond sizing and window analysis + +This note models the deployment-time choices unique to protocol v2: the +`base_bond` / `min_resolution_bond` floor, the registration and reveal window +lengths, anti-sniping headroom, and the per-address position cap. The models are +not a substitute for live telemetry, but they give deployers a repeatable way to +pick initial values and revisit them as usage changes. + +For the v1 bond-sizing framework — spam floors, dispute floors, and finalize-reward +constraints that still apply to `base_bond` — see [BOND_SIZING.md](BOND_SIZING.md). +This document extends that analysis with the three problems that are new in v2. + +## Background: v2 outcome rule + +Every disputed assertion produces a frozen eligible-weight total `W` at the +registration cutoff. `W` includes the asserter's `base_bond`, the disputer's +`base_bond`, and every third-party position registered before the cutoff. + +A side wins by **strict majority**: revealed weight for that side must exceed +`W / 2`. If neither side crosses that threshold when the reveal window closes, +the **optimistic timeout default** applies and the originally asserted outcome +stands. + +Settlement differs by terminal cause: + +- **Strict majority**: winning positions recover principal and share the losing + and non-revealed pool pro rata. Losing and non-revealed positions are forfeited. +- **Optimistic timeout**: all revealed positions (on either side) recover principal + and share only the non-revealed pool. Non-revealed positions are forfeited. + +Those two rules make non-revelation a double loss: the non-revealer forfeits its +bond and in a strict-majority scenario, its forfeiture is paid to the winning +side rather than returned to it. Under a timeout default, non-revealers still +forfeit to revealed positions. + +## Part 1: default-frequency model + +### The core asymmetry + +The optimistic timeout assigns the outcome to the asserted side unless a revealed +majority actively overturns it. Non-revealed weight sits in the denominator `W` +but contributes no votes. This means a large pool of registered-but-silent +positions can make an honest majority impossible without being a majority itself. + +Formally, let: + +- `W` = frozen eligible total +- `F` = revealed weight agreeing with the asserted outcome +- `A` = revealed weight against +- `N` = non-revealed weight (`N = W − F − A`) + +The assertion stands whenever `A ≤ W / 2`. Because `N > 0` inflates `W`, even a +large `A` may not cross the threshold. + +### Default-frequency formula + +For a dispute where the true outcome is *against* the asserted side, the assertion +nevertheless survives if: + +```text +A / W ≤ 0.5 +``` + +Define `t = (F + A) / W` as the **reveal turnout rate** (fraction of eligible +weight that actually reveals). For a symmetric dispute where roughly half the +revealed weight sides with each party: + +```text +A ≈ t × W / 2 +``` + +Then the assertion survives if: + +```text +t × W / 2 ≤ W / 2 → t ≤ 1.0 +``` + +That is always true — turnout alone cannot prevent a timeout. The meaningful +question is: what reveal turnout `t` is needed for the *against* side to reach a +strict majority when the split of revealed weight is skewed toward the losing +(assertion-supporting) side? + +Let `s` be the fraction of revealed weight on the *against* side (honesty +share). A strict-majority against-the-assertion requires: + +```text +s × t > 0.5 + → t > 0.5 / s +``` + +| Against-side honesty share `s` | Minimum turnout `t` for correction | +| ------------------------------ | ---------------------------------- | +| 100% (all revealers disagree) | > 50% | +| 80% | > 62.5% | +| 66% | > 75.8% | +| 51% | > 98% | +| 50% | impossible (tie never crosses 50%) | + +**Key finding**: when honest disagreers are 66% of revealers, three-quarters of +all eligible weight must reveal for correction. When they are 51%, virtually the +entire pool must reveal. Any non-reveal — absent staking, lost keys, sleeping +coordinators — benefits the asserted outcome. + +### The issue-body example + +The V2 design discussion raised this scenario explicitly: + +> 1% reveals for the assertion, 49% reveals against, 50% does not reveal. + +Here `W = 100`, `F = 1`, `A = 49`, `N = 50`. The against-side has 49 units, +but the threshold is `W / 2 = 50`. The assertion stands because `49 < 50`. + +More generally, any time `N ≥ 1` unit makes the strict-majority threshold +unattainable for the against-side, the assertion stands regardless of the +revealed margin. This is the intended behavior: the optimistic default favors the +status quo and treats abstention as implicit delegation to it. + +### Implications for window sizing + +The default-frequency risk is not eliminated by longer windows; it is controlled +by ensuring that enough bonded capital can *reach* the reveal phase. The levers +are: + +1. **`registration_duration_secs`** — a longer window lets more third-party + positions arrive, growing `W` with counter-stake rather than diluting a small + `W` with silence. +2. **`reveal_duration_secs`** — a longer reveal window lets coordinators organize + reveals. Too short a window and registered positions may silently miss it. +3. **`min_resolution_bond` = `base_bond`** — a higher floor means fewer positions + but each one is more economically committed. It does not by itself prevent + default. + +The practical guard against frequent timeout-by-silence is ensuring that the +*disputer* plus a realistic cohort of third-party registrants can represent a +strict majority of `W`. With only two equal fixed positions (`2 × base_bond`) and +no third parties, `W = 2 × base_bond`, `A = base_bond`, and `A / W = 0.5` — the +disputer's weight never exceeds half. A lone dispute *always* times out unless at +least one additional third party registers on the against side. See Part 3 for the +window-length tradeoffs that govern third-party participation. + +--- + +## Part 2: whale-capture model + +### Definitions + +A **whale** is a single address or coalition that can unilaterally reach strict +majority in one dispute. In v2 this means controlling more than `W / 2` of +eligible weight at the registration cutoff. + +Because weight is strictly proportional to bonded capital and splitting across +addresses provides no extra weight, the analysis is purely about capital +concentration. + +Let: + +- `B` = `base_bond` (asserter's and disputer's positions, each) +- `R_w` = whale's registration deposit (one or more top-ups summing to at most + `max_position`) +- `R_h` = total honest counter-stake registered by non-whale addresses +- `W = 2B + R_w + R_h` + +The whale controls strict majority when: + +```text +R_w > W / 2 + → R_w > (2B + R_w + R_h) / 2 + → 2R_w > 2B + R_w + R_h + → R_w > 2B + R_h +``` + +### Concentration threshold + +Define `c` as the whale's share of total eligible weight: + +```text +c = R_w / W +``` + +The whale reaches strict majority when `c > 0.5`. But the *cost* to reach that +threshold depends on how much honest counter-stake `R_h` is present: + +```text +Minimum R_w for capture = 2B + R_h + 1 unit +``` + +With zero counter-stake (`R_h = 0`): + +```text +R_w > 2B → three times the base bond secures majority +``` + +With counter-stake equal to the base bond (`R_h = B`): + +```text +R_w > 3B → four times the base bond required +``` + +With counter-stake equal to five times the base bond (`R_h = 5B`): + +```text +R_w > 7B → eight times the base bond required +``` + +Each additional unit of honest counter-stake raises the whale's capture cost +one-for-one, so growing `W` with genuine third-party positions is the primary +defense. + +### Role of `max_position` + +Setting `max_position < max_total_weight` prevents a single address from +contributing all of `W`. If `max_position = p × base_bond`: + +```text +Maximum single-address weight share = p / (2 + p) when R_h = 0 +``` + +| `max_position` (multiples of `base_bond`) | Max share of W (no counter-stake) | +| ----------------------------------------- | --------------------------------- | +| 1× (equal to each fixed party) | 33% | +| 2× | 50% exactly — cannot reach majority | +| 3× | 60% | +| 5× | 71% | +| 10× | 83% | +| ∞ (= `max_total_weight`) | 100% | + +**Key finding**: setting `max_position = 2 × base_bond` means a single address +with no counter-stake can only reach exactly 50%, which is not a strict majority. +Setting it at `3 × base_bond` allows capture with no counter-stake. This is the +most impactful single-parameter defense: even if no third party registers, +`max_position ≤ 2 × base_bond` prevents a whale from reaching majority on its own. + +However, `max_position ≤ 2 × base_bond` also caps legitimate counter-stake, which +means a single large honest voter cannot provide the full majority on its own +either. Whether that is acceptable depends on the deployment's expected electorate +size. For a deployment expecting 3+ participants in a contested dispute, tight +position caps are advisable. For a two-party deployment, the caps may be +irrelevant. + +### Self-hedging and the cost illusion + +A coalition that controls both the asserter role *and* a whale-sized registration +deposit can route the asserter's bond to the winning fixed side regardless of +outcome. If the coalition has asserter position `B` (agreeing) plus registration +`R_w > W / 2` (also agreeing), it controls majority at total cost `B + R_w`. If +the honest side wins instead, the coalition forfeits `R_w` but recovers `B` +through the asserter's principal. The coalition's *net exposure* is `R_w`, not +`B + R_w`. + +A deployer should therefore think of capture cost as **`R_w` alone** — the +capital that is genuinely at risk — not the notional `c × W`. A `max_position` +limit forces the whale to assemble multiple addresses, but linear weight prevents +splitting from amplifying its combined vote; it only complicates logistics and +raises gas costs slightly. + +--- + +## Part 3: window-length tradeoff model + +### Variables + +| Symbol | Meaning | +| --- | --- | +| `T_reg` | `registration_duration_secs` | +| `T_rev` | `reveal_duration_secs` | +| `T_hard` | `anti_snipe_hard_max_secs` | +| `T_ext` | `anti_snipe_extension_secs` | +| `τ_react` | Typical time for a new voter to notice the dispute and decide to register | +| `τ_coord` | Time needed to coordinate reveals off-chain (signal, salt collection) | +| `τ_atk` | Time an attacker needs to move capital into a sniped deposit | + +### Registration window: participation vs. capture speed + +A longer `T_reg` window increases expected third-party participation by giving +more potential voters time to notice the dispute and post bonds. Every unit of +honest counter-stake `R_h` added during registration raises the whale's capture +cost one-for-one (Part 2). But a longer window also extends the period during +which a well-funded attacker can observe accumulated positions, compute the +remaining gap to majority, and deploy exactly enough capital to cross it at +the last moment. + +The tradeoff: + +``` +Participation benefit peaks when: T_reg ≥ τ_react (typical voter latency) +Capture risk is manageable when: T_reg < time attacker needs to move capital +``` + +For most deployments these are the same order of magnitude (minutes to hours), +which is why anti-sniping exists. The practical guidance: + +- Use `T_reg ≥ τ_react` to capture genuine participation. +- Use `T_ext` (anti-snipe extension) to deter last-second position injections + that arrive after honest voters cannot respond. +- Cap extensions at `T_hard` to prevent an adversary from grieving registration + by repeatedly triggering extensions. + +### Anti-sniping parameters + +The soft deadline extends by `T_ext` when a qualifying deposit arrives within +`T_ext` seconds of the current deadline, but can never exceed `T_hard`. The +extension fires repeatedly if deposits keep arriving near the moving edge. + +```text +Maximum extensions before hard cap: floor((T_hard − T_reg) / T_ext) +``` + +For example, `T_reg = 3600`, `T_ext = 300`, `T_hard = 7200`: + +```text +Maximum extensions: floor((7200 − 3600) / 300) = 12 extensions of 5 minutes each +``` + +An attacker who tries to snipe must arrive at least `T_ext` seconds before the +hard deadline or its deposit will push the deadline out, giving honest voters +time to respond. Each extension also exposes the attacker's deposit size, letting +honest counter-stake calculate the correct response. + +Setting `T_ext` too small (e.g., 1 second) makes sniping easy; a last-second +deposit arrives and the extension is trivially short. Setting `T_ext` too large +(equal to `T_reg`) means a single late deposit nearly doubles the registration +window, which may itself be a griefing vector. A range of 5%–15% of `T_reg` is +generally appropriate. + +### Reveal window: participation vs. delay + +A longer `T_rev` gives registered voters more time to compute and submit their +reveal transaction. The risk of a short `T_rev` is that registered positions +silently miss the reveal deadline and become non-reveals, forfeiting their bond +and, more importantly, inflating `N` in a way that can prevent a legitimate +majority (Part 1). + +However, every second of `T_rev` adds directly to the total time from `dispute` +to `Resolved`. The total dispute lifecycle is approximately: + +```text +Total dispute time ≈ T_hard + T_rev +``` + +The tradeoff is: + +| `T_rev` choice | Effect on default frequency | Effect on finality latency | +| -------------- | --------------------------- | -------------------------- | +| Very short (< `τ_coord`) | High — reveal coordination may fail | Low | +| Moderate (≥ `τ_coord`) | Low — coordinators have time to act | Moderate | +| Very long | Negligible marginal gain after saturation | High | + +Recommended: set `T_rev ≥ τ_coord` with at least a 2× safety margin. For most +disputes, `τ_coord` is dominated by off-chain response time (monitoring, human +decision, client submission), not raw transaction throughput. 6 hours to 24 hours +is typical; sub-hour windows risk high default rates unless the deployment +guarantees automated reveal infrastructure. + +### Window-length summary table + +| Scenario | Longer window helps | Shorter window helps | +| -------- | ------------------- | -------------------- | +| High default frequency | `T_rev` (more reveal time) | — | +| Low third-party participation | `T_reg` (more registration time) | — | +| Last-second sniping | `T_ext`, `T_hard` | — | +| Slow resolution / time-sensitive outcomes | — | `T_reg`, `T_rev` | +| Griefing via repeated extensions | — | `T_hard` (set conservatively) | + +--- + +## Part 4: recommended starting profiles + +These profiles follow the same three-tier structure as [BOND_SIZING.md](BOND_SIZING.md). +They assume `min_resolution_bond = base_bond` (the contract enforces this). All +time values are in seconds; convert to your deployment's ledger approximation. + +### Inputs to collect + +Use token units consistently. The v1 inputs (`V_min`, `C_assert`, `C_dispute`, +`R_case`, `K_spam`, `K_dispute`, etc.) still apply to `base_bond`. The additional +v2 inputs are: + +| Symbol | Meaning | +| --- | --- | +| `τ_react` | Typical time for an interested third party to notice a dispute and register, in seconds. | +| `τ_coord` | Time needed for off-chain reveal coordination — collecting salts, computing commitments, submitting transactions. | +| `N_voters` | Expected number of distinct third-party registrants in a contested dispute. | +| `max_honest_stake` | Expected total third-party honest counter-stake in a typical dispute, in token units. | +| `V_dispute` | Economic value that could be captured by falsely resolving one assertion. | + +### Base-bond formula (extending v1) + +The v2 minimum bond satisfies all v1 constraints plus one additional check: + +```text +base_bond >= max( + R_case / max(1, K_spam), + R_case / max(1, K_dispute), + target_attacker_loss − min(C_assert, C_dispute), + min_finalizer_reward × 10_000 / max(1, reward_bps), + V_dispute / capture_cost_multiplier ← new in v2 +) +``` + +`capture_cost_multiplier` is the minimum multiple of `base_bond` an attacker must +stake to reach majority with no counter-stake. From Part 2, with zero +counter-stake this is `2B + 1`, meaning `capture_cost_multiplier ≈ 2`. With +realistic counter-stake the multiplier grows. Use `2` as the conservative +(zero-counter-stake) floor. + +Affordability cap (unchanged from v1): + +```text +base_bond <= V_min × max_acceptable_bond_share +``` + +### `max_position` guidance + +Set `max_position` as a multiple of `base_bond`: + +```text +max_position = k × base_bond, k ∈ [2, 20] +``` + +- `k = 2`: a single address cannot reach majority alone (even with no counter-stake). + Maximally whale-resistant but restricts legitimate large-stake participants. +- `k = 5–10`: a single address needs at least 5–10× honest counter-stake before + becoming a threat. Suitable for most deployments. +- `k = max_total_weight / base_bond`: no per-position constraint. + Use only in private / trusted deployments. + +### `max_total_weight` guidance + +```text +max_total_weight = m × base_bond, m ≥ max(10, N_voters × k + 2) +``` + +Set `m` large enough to accommodate the expected number of participants at full +`max_position` each, plus the two fixed parties. The contract arithmetic is +safe as long as `max_total_weight ≤ MAX_SETTLEMENT_TOTAL_WEIGHT`; the practical +guidance is to give yourself at least 5–10× headroom over the expected populated +`W` so legitimate counter-stake is never blocked. + +### Profile table + +| Profile | `base_bond` | `T_reg` | `T_ext` | `T_hard` | `T_rev` | `max_position` | `max_total_weight` | Use when | +| ------- | ----------- | ------- | ------- | -------- | ------- | -------------- | ------------------ | -------- | +| Private beta | 1×–2× spam floor | 1–4 h | 5 min | 2× `T_reg` | 4–12 h | 10× `base_bond` | 50× `base_bond` | Known users, coordinated reveals, low bot pressure. | +| Public testnet / low value | 2×–5× larger spam floor | 4–12 h | 10 min | 3× `T_reg` | 12–24 h | 5× `base_bond` | 100× `base_bond` | Open participation, moderate value, expect uncoordinated voters. | +| Higher-value mainnet candidate | 5×+ spam floor, within 5%–20% of `V_min` | 12–24 h | 15–30 min | 2×–4× `T_reg` | 24–48 h | 3× `base_bond` | 200× `base_bond` | Meaningful value, monitored reveals, audited deployment. | + +### Narrative guidance per profile + +#### Private beta + +The electorate is known. Reveals can be coordinated quickly. Default frequency +is low because coordinators will not silently miss the reveal window. The main +risk is a single insider dominating a dispute, so `max_position = 10 × base_bond` +is an informational bound rather than a security control (all participants are +trusted). A 1–4 hour registration window is long enough for beta testers to +notice a dispute; a 4–12 hour reveal window is long enough for manual +coordination. Set `anti_snipe_extension_secs` conservatively at 5 minutes to +prevent last-second test disputes from stalling registration. + +#### Public testnet / low value + +The electorate is open but economic stakes are low. Default frequency is a +secondary concern because a wrong resolution has limited financial impact. +The primary concern is UX: long enough windows so new users can register and +reveal without requiring dedicated keeper infrastructure, short enough that +resolutions complete within a day or two. A 4–12 hour registration window with +10-minute anti-snipe extensions and a 12–24 hour reveal window is a reasonable +starting point. Set `max_position = 5 × base_bond` to require at least 5 units +of honest counter-stake before a single whale can threaten majority. + +#### Higher-value mainnet candidate + +Every parameter is tightened toward security. Registration is 12–24 hours to +allow global participation across timezones. The reveal window is 24–48 hours +to give coordinators a full working day to organize reveals. `max_position = +3 × base_bond` forces a whale to recruit multiple addresses and raises logistics +cost. The anti-snipe extension is longer (15–30 minutes) to give honest +participants meaningful response time to a late deposit. The hard cap is 2–4× +the base registration window to allow 4–8 meaningful extensions without +permitting indefinite delay. The bond floor is computed at 5×+ the v1 spam/dispute +floor, checked against `V_dispute / 2`, and capped at 5%–20% of `V_min`. + +--- + +## Part 5: scenario checks + +### Default frequency check + +Before launch, verify that a realistic dispute can correct a false assertion. +With your chosen parameters: + +1. Assume only the disputer (one `base_bond` against) plus `N_voters` third parties + each posting `base_bond`. +2. Compute `W = 2 × base_bond × (1 + N_voters / 2)` under a symmetric scenario + where half the third parties side with each party. +3. Against-side weight: `base_bond × (1 + N_voters / 2)`. +4. Required threshold: `W / 2 + 1`. + +If `N_voters` is small (e.g., 1), the against-side has `1.5 × base_bond` against +a threshold of `1.5 × base_bond + 0.5`; correction requires exactly one more +third-party registrant on the honest side. A deployment expecting zero third +parties cannot deterministically correct a false assertion unless the disputer's +lone bond can tip the balance — which it cannot at `W = 2 × base_bond` (it +reaches exactly 50%, not strictly more than 50%). + +**Rule of thumb**: budget `N_voters ≥ 3` realistically achievable third-party +registrants for a deployment that intends to correct false assertions without +relying on a dominant single voter. + +### Whale-capture check + +For your chosen `base_bond`, `max_position`, and expected `max_honest_stake`: + +```text +Minimum capture bond = 2 × base_bond + max_honest_stake + 1 unit +``` + +If `minimum capture bond > max_position`, capture is impossible for a single +address regardless of counter-stake. If `minimum capture bond ≤ max_position`, +the whale risk exists and should be controlled by expecting `max_honest_stake` +to be present in contested disputes. + +Worked example (higher-value mainnet candidate profile): + +- `base_bond = 100` units +- `max_position = 300` units (3×) +- Expected honest counter-stake: `200` units (two third parties at `base_bond` each) + +```text +Minimum capture: 2(100) + 200 + 1 = 401 units > max_position (300) +``` + +A single address cannot reach majority even with no honest counter-stake beyond +the two fixed parties. The deployment is whale-resistant by construction under +this example. + +### Window-length sanity check + +Verify: + +```text +T_rev ≥ 2 × τ_coord (2× safety margin on reveal coordination) +T_reg ≥ τ_react (voters can notice and register) +T_ext ≥ τ_atk / 10 (extension is nontrivial relative to attacker response time) +T_hard ≤ T_reg + 20 × T_ext (hard cap prevents indefinite extension griefing) +``` + +If `T_rev < τ_coord`, shorten the coordination process, add keeper automation, or +increase `T_rev`. If `T_hard` would exceed your acceptable total dispute lifetime +(`T_hard + T_rev`), tighten the anti-snipe parameters or reduce `T_ext`. + +--- + +## Monitoring and adjustment + +Review after every testnet campaign and before mainnet launch: + +- Fraction of disputes that end in `OptimisticTimeout` vs. `StrictMajority`. + A high timeout rate with many registered positions suggests the reveal window is + too short or coordination is breaking down. A high timeout rate with few or no + third-party registrants may indicate the registration window or bond floor is too + high for the expected electorate. +- Distribution of `W` across disputes. If `W ≈ 2 × base_bond` consistently, + third-party participation is absent; revisit window lengths and bond sizing. +- Non-reveal rate among registered third-party positions. High non-reveal rates + inflate `N` and drive default frequency. Investigate whether `T_rev` is too + short, whether keepers are missing reveals, or whether registrants are + strategically abstaining. +- `max_position` hits. If deposits are being rejected for exceeding `max_position`, + either the cap is too tight for the dispute's capital or a whale is probing. + Examine addresses to distinguish the two. +- Total dispute lifecycle time (from `dispute` to `Resolved`). If disputes are + consistently completing well inside the maximum window, the windows may safely + be shortened for future deployments; if they are consistently running to the + deadline, lengthen the reveal window first. + +Raise `base_bond` if capture attempts cluster around small numbers of addresses +or if false assertions survive repeated disputes. Lengthen `T_rev` if the +non-reveal rate is high. Tighten `max_position` if large single-address positions +appear in contested disputes. Revisit the full calculation whenever the token +price, assertion value distribution, or expected electorate changes materially. From 0e763007a576c63ec1c7370a99a9bc1dd4a456f7 Mon Sep 17 00:00:00 2001 From: Kayce10 Date: Sat, 29 Aug 2026 07:51:47 +0000 Subject: [PATCH 2/5] docs: address reviewer feedback on V2_BOND_SIZING - Replace all em/en dashes with plain punctuation throughout - Fix 'three/four/eight times' phrasing in Part 2 to match Part 4's capture_cost_multiplier ~= 2; whale needs just over 2B, not 3B - Reconcile threshold formula in Part 5: use side_weight > W - side_weight (the contract's actual check) and floor(W/2)+1 for integer W consistently, replacing the inconsistent W/2+1 vs W/2+0.5 in the worked example - Move SUMMARY.md entry under Protocol v2 Resolution Proposal --- docs/src/SUMMARY.md | 1 + docs/src/V2_BOND_SIZING.md | 231 +++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 113 deletions(-) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 7bd89b0..b5ba30e 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -6,6 +6,7 @@ - [Resolver Self-Rotation Design](ROTATION_DESIGN.md) - [Protocol v2 Resolution Proposal](V2_RESOLUTION.md) - [V2 Claim Identifier and Evidence Convention](V2_CLAIM_IDENTIFIER.md) + - [V2 Bond Sizing and Window Analysis](V2_BOND_SIZING.md) - [Contract Reference](CONTRACT.md) - [Contract Reference (v2)](CONTRACT_V2.md) - [Deployment & Operations](DEPLOYMENT.md) diff --git a/docs/src/V2_BOND_SIZING.md b/docs/src/V2_BOND_SIZING.md index f65ccf4..d20a514 100644 --- a/docs/src/V2_BOND_SIZING.md +++ b/docs/src/V2_BOND_SIZING.md @@ -6,8 +6,8 @@ lengths, anti-sniping headroom, and the per-address position cap. The models are not a substitute for live telemetry, but they give deployers a repeatable way to pick initial values and revisit them as usage changes. -For the v1 bond-sizing framework — spam floors, dispute floors, and finalize-reward -constraints that still apply to `base_bond` — see [BOND_SIZING.md](BOND_SIZING.md). +For the v1 bond-sizing framework (spam floors, dispute floors, and finalize-reward +constraints that still apply to `base_bond`) see [BOND_SIZING.md](BOND_SIZING.md). This document extends that analysis with the three problems that are new in v2. ## Background: v2 outcome rule @@ -47,9 +47,9 @@ Formally, let: - `W` = frozen eligible total - `F` = revealed weight agreeing with the asserted outcome - `A` = revealed weight against -- `N` = non-revealed weight (`N = W − F − A`) +- `N` = non-revealed weight (`N = W - F - A`) -The assertion stands whenever `A ≤ W / 2`. Because `N > 0` inflates `W`, even a +The assertion stands whenever `A <= W / 2`. Because `N > 0` inflates `W`, even a large `A` may not cross the threshold. ### Default-frequency formula @@ -58,7 +58,7 @@ For a dispute where the true outcome is *against* the asserted side, the asserti nevertheless survives if: ```text -A / W ≤ 0.5 +A / W <= 0.5 ``` Define `t = (F + A) / W` as the **reveal turnout rate** (fraction of eligible @@ -66,26 +66,26 @@ weight that actually reveals). For a symmetric dispute where roughly half the revealed weight sides with each party: ```text -A ≈ t × W / 2 +A ~= t x W / 2 ``` Then the assertion survives if: ```text -t × W / 2 ≤ W / 2 → t ≤ 1.0 +t x W / 2 <= W / 2 -> t <= 1.0 ``` -That is always true — turnout alone cannot prevent a timeout. The meaningful -question is: what reveal turnout `t` is needed for the *against* side to reach a +That is always true: turnout alone cannot prevent a timeout. The meaningful +question is what reveal turnout `t` is needed for the *against* side to reach a strict majority when the split of revealed weight is skewed toward the losing -(assertion-supporting) side? +(assertion-supporting) side. Let `s` be the fraction of revealed weight on the *against* side (honesty share). A strict-majority against-the-assertion requires: ```text -s × t > 0.5 - → t > 0.5 / s +s x t > 0.5 + -> t > 0.5 / s ``` | Against-side honesty share `s` | Minimum turnout `t` for correction | @@ -98,8 +98,8 @@ s × t > 0.5 **Key finding**: when honest disagreers are 66% of revealers, three-quarters of all eligible weight must reveal for correction. When they are 51%, virtually the -entire pool must reveal. Any non-reveal — absent staking, lost keys, sleeping -coordinators — benefits the asserted outcome. +entire pool must reveal. Any non-reveal (absent staking, lost keys, sleeping +coordinators) benefits the asserted outcome. ### The issue-body example @@ -110,7 +110,7 @@ The V2 design discussion raised this scenario explicitly: Here `W = 100`, `F = 1`, `A = 49`, `N = 50`. The against-side has 49 units, but the threshold is `W / 2 = 50`. The assertion stands because `49 < 50`. -More generally, any time `N ≥ 1` unit makes the strict-majority threshold +More generally, any time `N >= 1` unit makes the strict-majority threshold unattainable for the against-side, the assertion stands regardless of the revealed margin. This is the intended behavior: the optimistic default favors the status quo and treats abstention as implicit delegation to it. @@ -121,19 +121,19 @@ The default-frequency risk is not eliminated by longer windows; it is controlled by ensuring that enough bonded capital can *reach* the reveal phase. The levers are: -1. **`registration_duration_secs`** — a longer window lets more third-party +1. **`registration_duration_secs`**: a longer window lets more third-party positions arrive, growing `W` with counter-stake rather than diluting a small `W` with silence. -2. **`reveal_duration_secs`** — a longer reveal window lets coordinators organize +2. **`reveal_duration_secs`**: a longer reveal window lets coordinators organize reveals. Too short a window and registered positions may silently miss it. -3. **`min_resolution_bond` = `base_bond`** — a higher floor means fewer positions +3. **`min_resolution_bond` = `base_bond`**: a higher floor means fewer positions but each one is more economically committed. It does not by itself prevent default. The practical guard against frequent timeout-by-silence is ensuring that the *disputer* plus a realistic cohort of third-party registrants can represent a -strict majority of `W`. With only two equal fixed positions (`2 × base_bond`) and -no third parties, `W = 2 × base_bond`, `A = base_bond`, and `A / W = 0.5` — the +strict majority of `W`. With only two equal fixed positions (`2 x base_bond`) and +no third parties, `W = 2 x base_bond`, `A = base_bond`, and `A / W = 0.5`; the disputer's weight never exceeds half. A lone dispute *always* times out unless at least one additional third party registers on the against side. See Part 3 for the window-length tradeoffs that govern third-party participation. @@ -164,9 +164,9 @@ The whale controls strict majority when: ```text R_w > W / 2 - → R_w > (2B + R_w + R_h) / 2 - → 2R_w > 2B + R_w + R_h - → R_w > 2B + R_h + -> R_w > (2B + R_w + R_h) / 2 + -> 2R_w > 2B + R_w + R_h + -> R_w > 2B + R_h ``` ### Concentration threshold @@ -187,19 +187,19 @@ Minimum R_w for capture = 2B + R_h + 1 unit With zero counter-stake (`R_h = 0`): ```text -R_w > 2B → three times the base bond secures majority +R_w > 2B -> just over twice the base bond is enough to capture majority ``` With counter-stake equal to the base bond (`R_h = B`): ```text -R_w > 3B → four times the base bond required +R_w > 3B -> just over three times the base bond required ``` With counter-stake equal to five times the base bond (`R_h = 5B`): ```text -R_w > 7B → eight times the base bond required +R_w > 7B -> just over seven times the base bond required ``` Each additional unit of honest counter-stake raises the whale's capture cost @@ -209,7 +209,7 @@ defense. ### Role of `max_position` Setting `max_position < max_total_weight` prevents a single address from -contributing all of `W`. If `max_position = p × base_bond`: +contributing all of `W`. If `max_position = p x base_bond`: ```text Maximum single-address weight share = p / (2 + p) when R_h = 0 @@ -217,20 +217,20 @@ Maximum single-address weight share = p / (2 + p) when R_h = 0 | `max_position` (multiples of `base_bond`) | Max share of W (no counter-stake) | | ----------------------------------------- | --------------------------------- | -| 1× (equal to each fixed party) | 33% | -| 2× | 50% exactly — cannot reach majority | -| 3× | 60% | -| 5× | 71% | -| 10× | 83% | -| ∞ (= `max_total_weight`) | 100% | - -**Key finding**: setting `max_position = 2 × base_bond` means a single address +| 1x (equal to each fixed party) | 33% | +| 2x | 50% exactly; cannot reach majority | +| 3x | 60% | +| 5x | 71% | +| 10x | 83% | +| unlimited (= `max_total_weight`) | 100% | + +**Key finding**: setting `max_position = 2 x base_bond` means a single address with no counter-stake can only reach exactly 50%, which is not a strict majority. -Setting it at `3 × base_bond` allows capture with no counter-stake. This is the +Setting it at `3 x base_bond` allows capture with no counter-stake. This is the most impactful single-parameter defense: even if no third party registers, -`max_position ≤ 2 × base_bond` prevents a whale from reaching majority on its own. +`max_position <= 2 x base_bond` prevents a whale from reaching majority on its own. -However, `max_position ≤ 2 × base_bond` also caps legitimate counter-stake, which +However, `max_position <= 2 x base_bond` also caps legitimate counter-stake, which means a single large honest voter cannot provide the full majority on its own either. Whether that is acceptable depends on the deployment's expected electorate size. For a deployment expecting 3+ participants in a contested dispute, tight @@ -247,8 +247,8 @@ the honest side wins instead, the coalition forfeits `R_w` but recovers `B` through the asserter's principal. The coalition's *net exposure* is `R_w`, not `B + R_w`. -A deployer should therefore think of capture cost as **`R_w` alone** — the -capital that is genuinely at risk — not the notional `c × W`. A `max_position` +A deployer should therefore think of capture cost as **`R_w` alone** (the +capital that is genuinely at risk), not the notional `c x W`. A `max_position` limit forces the whale to assemble multiple addresses, but linear weight prevents splitting from amplifying its combined vote; it only complicates logistics and raises gas costs slightly. @@ -265,9 +265,9 @@ raises gas costs slightly. | `T_rev` | `reveal_duration_secs` | | `T_hard` | `anti_snipe_hard_max_secs` | | `T_ext` | `anti_snipe_extension_secs` | -| `τ_react` | Typical time for a new voter to notice the dispute and decide to register | -| `τ_coord` | Time needed to coordinate reveals off-chain (signal, salt collection) | -| `τ_atk` | Time an attacker needs to move capital into a sniped deposit | +| `t_react` | Typical time for a new voter to notice the dispute and decide to register | +| `t_coord` | Time needed to coordinate reveals off-chain (signal, salt collection) | +| `t_atk` | Time an attacker needs to move capital into a sniped deposit | ### Registration window: participation vs. capture speed @@ -282,14 +282,14 @@ the last moment. The tradeoff: ``` -Participation benefit peaks when: T_reg ≥ τ_react (typical voter latency) +Participation benefit peaks when: T_reg >= t_react (typical voter latency) Capture risk is manageable when: T_reg < time attacker needs to move capital ``` For most deployments these are the same order of magnitude (minutes to hours), which is why anti-sniping exists. The practical guidance: -- Use `T_reg ≥ τ_react` to capture genuine participation. +- Use `T_reg >= t_react` to capture genuine participation. - Use `T_ext` (anti-snipe extension) to deter last-second position injections that arrive after honest voters cannot respond. - Cap extensions at `T_hard` to prevent an adversary from grieving registration @@ -302,13 +302,13 @@ The soft deadline extends by `T_ext` when a qualifying deposit arrives within extension fires repeatedly if deposits keep arriving near the moving edge. ```text -Maximum extensions before hard cap: floor((T_hard − T_reg) / T_ext) +Maximum extensions before hard cap: floor((T_hard - T_reg) / T_ext) ``` For example, `T_reg = 3600`, `T_ext = 300`, `T_hard = 7200`: ```text -Maximum extensions: floor((7200 − 3600) / 300) = 12 extensions of 5 minutes each +Maximum extensions: floor((7200 - 3600) / 300) = 12 extensions of 5 minutes each ``` An attacker who tries to snipe must arrive at least `T_ext` seconds before the @@ -319,7 +319,7 @@ honest counter-stake calculate the correct response. Setting `T_ext` too small (e.g., 1 second) makes sniping easy; a last-second deposit arrives and the extension is trivially short. Setting `T_ext` too large (equal to `T_reg`) means a single late deposit nearly doubles the registration -window, which may itself be a griefing vector. A range of 5%–15% of `T_reg` is +window, which may itself be a griefing vector. A range of 5%-15% of `T_reg` is generally appropriate. ### Reveal window: participation vs. delay @@ -334,19 +334,19 @@ However, every second of `T_rev` adds directly to the total time from `dispute` to `Resolved`. The total dispute lifecycle is approximately: ```text -Total dispute time ≈ T_hard + T_rev +Total dispute time ~= T_hard + T_rev ``` The tradeoff is: | `T_rev` choice | Effect on default frequency | Effect on finality latency | | -------------- | --------------------------- | -------------------------- | -| Very short (< `τ_coord`) | High — reveal coordination may fail | Low | -| Moderate (≥ `τ_coord`) | Low — coordinators have time to act | Moderate | -| Very long | Negligible marginal gain after saturation | High | +| Very short (< `t_coord`) | High: reveal coordination may fail | Low | +| Moderate (>= `t_coord`) | Low: coordinators have time to act | Moderate | +| Very long | Negligible marginal gain after saturation | High | -Recommended: set `T_rev ≥ τ_coord` with at least a 2× safety margin. For most -disputes, `τ_coord` is dominated by off-chain response time (monitoring, human +Recommended: set `T_rev >= t_coord` with at least a 2x safety margin. For most +disputes, `t_coord` is dominated by off-chain response time (monitoring, human decision, client submission), not raw transaction throughput. 6 hours to 24 hours is typical; sub-hour windows risk high default rates unless the deployment guarantees automated reveal infrastructure. @@ -355,11 +355,11 @@ guarantees automated reveal infrastructure. | Scenario | Longer window helps | Shorter window helps | | -------- | ------------------- | -------------------- | -| High default frequency | `T_rev` (more reveal time) | — | -| Low third-party participation | `T_reg` (more registration time) | — | -| Last-second sniping | `T_ext`, `T_hard` | — | -| Slow resolution / time-sensitive outcomes | — | `T_reg`, `T_rev` | -| Griefing via repeated extensions | — | `T_hard` (set conservatively) | +| High default frequency | `T_rev` (more reveal time) | n/a | +| Low third-party participation | `T_reg` (more registration time) | n/a | +| Last-second sniping | `T_ext`, `T_hard` | n/a | +| Slow resolution / time-sensitive outcomes | n/a | `T_reg`, `T_rev` | +| Griefing via repeated extensions | n/a | `T_hard` (set conservatively) | --- @@ -377,8 +377,8 @@ v2 inputs are: | Symbol | Meaning | | --- | --- | -| `τ_react` | Typical time for an interested third party to notice a dispute and register, in seconds. | -| `τ_coord` | Time needed for off-chain reveal coordination — collecting salts, computing commitments, submitting transactions. | +| `t_react` | Typical time for an interested third party to notice a dispute and register, in seconds. | +| `t_coord` | Time needed for off-chain reveal coordination: collecting salts, computing commitments, submitting transactions. | | `N_voters` | Expected number of distinct third-party registrants in a contested dispute. | | `max_honest_stake` | Expected total third-party honest counter-stake in a typical dispute, in token units. | | `V_dispute` | Economic value that could be captured by falsely resolving one assertion. | @@ -391,22 +391,22 @@ The v2 minimum bond satisfies all v1 constraints plus one additional check: base_bond >= max( R_case / max(1, K_spam), R_case / max(1, K_dispute), - target_attacker_loss − min(C_assert, C_dispute), - min_finalizer_reward × 10_000 / max(1, reward_bps), - V_dispute / capture_cost_multiplier ← new in v2 + target_attacker_loss - min(C_assert, C_dispute), + min_finalizer_reward x 10_000 / max(1, reward_bps), + V_dispute / capture_cost_multiplier <- new in v2 ) ``` `capture_cost_multiplier` is the minimum multiple of `base_bond` an attacker must stake to reach majority with no counter-stake. From Part 2, with zero -counter-stake this is `2B + 1`, meaning `capture_cost_multiplier ≈ 2`. With +counter-stake this is `2B + 1`, meaning `capture_cost_multiplier ~= 2`. With realistic counter-stake the multiplier grows. Use `2` as the conservative (zero-counter-stake) floor. Affordability cap (unchanged from v1): ```text -base_bond <= V_min × max_acceptable_bond_share +base_bond <= V_min x max_acceptable_bond_share ``` ### `max_position` guidance @@ -414,12 +414,12 @@ base_bond <= V_min × max_acceptable_bond_share Set `max_position` as a multiple of `base_bond`: ```text -max_position = k × base_bond, k ∈ [2, 20] +max_position = k x base_bond, k in [2, 20] ``` - `k = 2`: a single address cannot reach majority alone (even with no counter-stake). Maximally whale-resistant but restricts legitimate large-stake participants. -- `k = 5–10`: a single address needs at least 5–10× honest counter-stake before +- `k = 5-10`: a single address needs at least 5-10x honest counter-stake before becoming a threat. Suitable for most deployments. - `k = max_total_weight / base_bond`: no per-position constraint. Use only in private / trusted deployments. @@ -427,22 +427,22 @@ max_position = k × base_bond, k ∈ [2, 20] ### `max_total_weight` guidance ```text -max_total_weight = m × base_bond, m ≥ max(10, N_voters × k + 2) +max_total_weight = m x base_bond, m >= max(10, N_voters x k + 2) ``` Set `m` large enough to accommodate the expected number of participants at full `max_position` each, plus the two fixed parties. The contract arithmetic is -safe as long as `max_total_weight ≤ MAX_SETTLEMENT_TOTAL_WEIGHT`; the practical -guidance is to give yourself at least 5–10× headroom over the expected populated +safe as long as `max_total_weight <= MAX_SETTLEMENT_TOTAL_WEIGHT`; the practical +guidance is to give yourself at least 5-10x headroom over the expected populated `W` so legitimate counter-stake is never blocked. ### Profile table | Profile | `base_bond` | `T_reg` | `T_ext` | `T_hard` | `T_rev` | `max_position` | `max_total_weight` | Use when | | ------- | ----------- | ------- | ------- | -------- | ------- | -------------- | ------------------ | -------- | -| Private beta | 1×–2× spam floor | 1–4 h | 5 min | 2× `T_reg` | 4–12 h | 10× `base_bond` | 50× `base_bond` | Known users, coordinated reveals, low bot pressure. | -| Public testnet / low value | 2×–5× larger spam floor | 4–12 h | 10 min | 3× `T_reg` | 12–24 h | 5× `base_bond` | 100× `base_bond` | Open participation, moderate value, expect uncoordinated voters. | -| Higher-value mainnet candidate | 5×+ spam floor, within 5%–20% of `V_min` | 12–24 h | 15–30 min | 2×–4× `T_reg` | 24–48 h | 3× `base_bond` | 200× `base_bond` | Meaningful value, monitored reveals, audited deployment. | +| Private beta | 1x-2x spam floor | 1-4 h | 5 min | 2x `T_reg` | 4-12 h | 10x `base_bond` | 50x `base_bond` | Known users, coordinated reveals, low bot pressure. | +| Public testnet / low value | 2x-5x larger spam floor | 4-12 h | 10 min | 3x `T_reg` | 12-24 h | 5x `base_bond` | 100x `base_bond` | Open participation, moderate value, expect uncoordinated voters. | +| Higher-value mainnet candidate | 5x+ spam floor, within 5%-20% of `V_min` | 12-24 h | 15-30 min | 2x-4x `T_reg` | 24-48 h | 3x `base_bond` | 200x `base_bond` | Meaningful value, monitored reveals, audited deployment. | ### Narrative guidance per profile @@ -450,10 +450,10 @@ guidance is to give yourself at least 5–10× headroom over the expected popula The electorate is known. Reveals can be coordinated quickly. Default frequency is low because coordinators will not silently miss the reveal window. The main -risk is a single insider dominating a dispute, so `max_position = 10 × base_bond` +risk is a single insider dominating a dispute, so `max_position = 10 x base_bond` is an informational bound rather than a security control (all participants are -trusted). A 1–4 hour registration window is long enough for beta testers to -notice a dispute; a 4–12 hour reveal window is long enough for manual +trusted). A 1-4 hour registration window is long enough for beta testers to +notice a dispute; a 4-12 hour reveal window is long enough for manual coordination. Set `anti_snipe_extension_secs` conservatively at 5 minutes to prevent last-second test disputes from stalling registration. @@ -463,22 +463,22 @@ The electorate is open but economic stakes are low. Default frequency is a secondary concern because a wrong resolution has limited financial impact. The primary concern is UX: long enough windows so new users can register and reveal without requiring dedicated keeper infrastructure, short enough that -resolutions complete within a day or two. A 4–12 hour registration window with -10-minute anti-snipe extensions and a 12–24 hour reveal window is a reasonable -starting point. Set `max_position = 5 × base_bond` to require at least 5 units +resolutions complete within a day or two. A 4-12 hour registration window with +10-minute anti-snipe extensions and a 12-24 hour reveal window is a reasonable +starting point. Set `max_position = 5 x base_bond` to require at least 5 units of honest counter-stake before a single whale can threaten majority. #### Higher-value mainnet candidate -Every parameter is tightened toward security. Registration is 12–24 hours to -allow global participation across timezones. The reveal window is 24–48 hours +Every parameter is tightened toward security. Registration is 12-24 hours to +allow global participation across timezones. The reveal window is 24-48 hours to give coordinators a full working day to organize reveals. `max_position = -3 × base_bond` forces a whale to recruit multiple addresses and raises logistics -cost. The anti-snipe extension is longer (15–30 minutes) to give honest -participants meaningful response time to a late deposit. The hard cap is 2–4× -the base registration window to allow 4–8 meaningful extensions without -permitting indefinite delay. The bond floor is computed at 5×+ the v1 spam/dispute -floor, checked against `V_dispute / 2`, and capped at 5%–20% of `V_min`. +3 x base_bond` forces a whale to recruit multiple addresses and raises logistics +cost. The anti-snipe extension is longer (15-30 minutes) to give honest +participants meaningful response time to a late deposit. The hard cap is 2-4x +the base registration window to allow 4-8 meaningful extensions without +permitting indefinite delay. The bond floor is computed at 5x+ the v1 spam/dispute +floor, checked against `V_dispute / 2`, and capped at 5%-20% of `V_min`. --- @@ -491,19 +491,24 @@ With your chosen parameters: 1. Assume only the disputer (one `base_bond` against) plus `N_voters` third parties each posting `base_bond`. -2. Compute `W = 2 × base_bond × (1 + N_voters / 2)` under a symmetric scenario +2. Compute `W = 2 x base_bond x (1 + N_voters / 2)` under a symmetric scenario where half the third parties side with each party. -3. Against-side weight: `base_bond × (1 + N_voters / 2)`. -4. Required threshold: `W / 2 + 1`. - -If `N_voters` is small (e.g., 1), the against-side has `1.5 × base_bond` against -a threshold of `1.5 × base_bond + 0.5`; correction requires exactly one more -third-party registrant on the honest side. A deployment expecting zero third -parties cannot deterministically correct a false assertion unless the disputer's -lone bond can tip the balance — which it cannot at `W = 2 × base_bond` (it -reaches exactly 50%, not strictly more than 50%). - -**Rule of thumb**: budget `N_voters ≥ 3` realistically achievable third-party +3. Against-side weight: `base_bond x (1 + N_voters / 2)`. +4. Required threshold: strictly more than `W / 2`. The contract uses the + comparison `side_weight > W - side_weight` (equivalently `2 x side_weight > W`), + which avoids doubling overflow and handles both even and odd `W` correctly. + For an integer `W`, this means against-side weight must be at least + `floor(W / 2) + 1`. + +If `N_voters` is small (e.g., 1), then `W = 3 x base_bond`, against-side weight +is `1.5 x base_bond`, and the required threshold is `floor(3B / 2) + 1`; with +integer bonds, against-side needs at least `floor(3B / 2) + 1` units. For +`base_bond = 2` this is 4 against 3, requiring one more unit on the honest side. +A deployment expecting zero third parties cannot deterministically correct a false +assertion: the disputer's lone bond reaches exactly `W / 2` at `W = 2 x base_bond`, +which does not satisfy `side_weight > W - side_weight`. + +**Rule of thumb**: budget `N_voters >= 3` realistically achievable third-party registrants for a deployment that intends to correct false assertions without relying on a dominant single voter. @@ -512,18 +517,18 @@ relying on a dominant single voter. For your chosen `base_bond`, `max_position`, and expected `max_honest_stake`: ```text -Minimum capture bond = 2 × base_bond + max_honest_stake + 1 unit +Minimum capture bond = 2 x base_bond + max_honest_stake + 1 unit ``` If `minimum capture bond > max_position`, capture is impossible for a single -address regardless of counter-stake. If `minimum capture bond ≤ max_position`, +address regardless of counter-stake. If `minimum capture bond <= max_position`, the whale risk exists and should be controlled by expecting `max_honest_stake` to be present in contested disputes. Worked example (higher-value mainnet candidate profile): - `base_bond = 100` units -- `max_position = 300` units (3×) +- `max_position = 300` units (3x) - Expected honest counter-stake: `200` units (two third parties at `base_bond` each) ```text @@ -539,13 +544,13 @@ this example. Verify: ```text -T_rev ≥ 2 × τ_coord (2× safety margin on reveal coordination) -T_reg ≥ τ_react (voters can notice and register) -T_ext ≥ τ_atk / 10 (extension is nontrivial relative to attacker response time) -T_hard ≤ T_reg + 20 × T_ext (hard cap prevents indefinite extension griefing) +T_rev >= 2 x t_coord (2x safety margin on reveal coordination) +T_reg >= t_react (voters can notice and register) +T_ext >= t_atk / 10 (extension is nontrivial relative to attacker response time) +T_hard <= T_reg + 20 x T_ext (hard cap prevents indefinite extension griefing) ``` -If `T_rev < τ_coord`, shorten the coordination process, add keeper automation, or +If `T_rev < t_coord`, shorten the coordination process, add keeper automation, or increase `T_rev`. If `T_hard` would exceed your acceptable total dispute lifetime (`T_hard + T_rev`), tighten the anti-snipe parameters or reduce `T_ext`. @@ -555,12 +560,12 @@ increase `T_rev`. If `T_hard` would exceed your acceptable total dispute lifetim Review after every testnet campaign and before mainnet launch: -- Fraction of disputes that end in `OptimisticTimeout` vs. `StrictMajority`. - A high timeout rate with many registered positions suggests the reveal window is +- Fraction of disputes that end in `OptimisticTimeout` vs. `StrictMajority`. A + high timeout rate with many registered positions suggests the reveal window is too short or coordination is breaking down. A high timeout rate with few or no - third-party registrants may indicate the registration window or bond floor is too - high for the expected electorate. -- Distribution of `W` across disputes. If `W ≈ 2 × base_bond` consistently, + third-party registrants may indicate the registration window or bond floor is + too high for the expected electorate. +- Distribution of `W` across disputes. If `W ~= 2 x base_bond` consistently, third-party participation is absent; revisit window lengths and bond sizing. - Non-reveal rate among registered third-party positions. High non-reveal rates inflate `N` and drive default frequency. Investigate whether `T_rev` is too From 636d4df7454ac9591fe11777d71f80890e6a3d98 Mon Sep 17 00:00:00 2001 From: Kayce10 Date: Sat, 29 Aug 2026 07:55:56 +0000 Subject: [PATCH 3/5] docs: remove duplicate V2_BOND_SIZING entry from SUMMARY.md --- docs/src/SUMMARY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index b5ba30e..7bd89b0 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -6,7 +6,6 @@ - [Resolver Self-Rotation Design](ROTATION_DESIGN.md) - [Protocol v2 Resolution Proposal](V2_RESOLUTION.md) - [V2 Claim Identifier and Evidence Convention](V2_CLAIM_IDENTIFIER.md) - - [V2 Bond Sizing and Window Analysis](V2_BOND_SIZING.md) - [Contract Reference](CONTRACT.md) - [Contract Reference (v2)](CONTRACT_V2.md) - [Deployment & Operations](DEPLOYMENT.md) From bae9ce2c247322b2781734e93fc584bdaa14b907 Mon Sep 17 00:00:00 2001 From: Kayce10 Date: Sat, 29 Aug 2026 10:47:10 +0000 Subject: [PATCH 4/5] docs: fix two reviewer findings in V2_BOND_SIZING - Self-hedging section: remove false claim that the asserter bond is recovered when the honest side wins. settle() for StrictMajorityAgainst pays only positions with agrees_with_outcome == Some(false); the asserter's Fixed(true) position has Some(true) and is forfeited along with R_w. Real net exposure on loss is B + R_w, not R_w alone. Rewrite the section to reflect the correct settlement mechanic and state capture cost as B + R_w throughout. - N_voters rule of thumb: add a clarifying paragraph making explicit that N_voters >= 3 is a floor for a healthy electorate, not a sufficient condition for correction. The symmetric-split model shows against-side weight equals exactly W / 2 for any N_voters; correction requires an honest-side imbalance in revealed weight, not just a minimum headcount. --- docs/src/V2_BOND_SIZING.md | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/docs/src/V2_BOND_SIZING.md b/docs/src/V2_BOND_SIZING.md index d20a514..d9d929e 100644 --- a/docs/src/V2_BOND_SIZING.md +++ b/docs/src/V2_BOND_SIZING.md @@ -240,18 +240,22 @@ irrelevant. ### Self-hedging and the cost illusion A coalition that controls both the asserter role *and* a whale-sized registration -deposit can route the asserter's bond to the winning fixed side regardless of -outcome. If the coalition has asserter position `B` (agreeing) plus registration -`R_w > W / 2` (also agreeing), it controls majority at total cost `B + R_w`. If -the honest side wins instead, the coalition forfeits `R_w` but recovers `B` -through the asserter's principal. The coalition's *net exposure* is `R_w`, not -`B + R_w`. - -A deployer should therefore think of capture cost as **`R_w` alone** (the -capital that is genuinely at risk), not the notional `c x W`. A `max_position` -limit forces the whale to assemble multiple addresses, but linear weight prevents -splitting from amplifying its combined vote; it only complicates logistics and -raises gas costs slightly. +deposit can attempt to control both the assertion and the majority vote. If the +coalition has asserter position `B` (agreeing) plus registration `R_w > W / 2` +(also agreeing), it controls majority at total cost `B + R_w`. If the honest +side wins instead, the `StrictMajorityAgainst` settlement rule pays only +positions where `agrees_with_outcome == Some(false)`; the asserter's +`Fixed(true)` position has `agrees_with_outcome == Some(true)` and is therefore +forfeited along with `R_w`. The coalition's real net exposure when it loses is +`B + R_w`, not `R_w` alone. There is no self-hedging benefit: the asserter bond +does not reduce the coalition's downside. + +A deployer should therefore think of capture cost as **`B + R_w`** in both the +success and the failure case. The minimum capital at risk for a capture attempt +is `B + R_w`, where `R_w > 2B + R_h`. A `max_position` limit forces the whale +to assemble multiple addresses, but linear weight prevents splitting from +amplifying its combined vote; it only complicates logistics and raises capital +requirements slightly. --- @@ -510,7 +514,15 @@ which does not satisfy `side_weight > W - side_weight`. **Rule of thumb**: budget `N_voters >= 3` realistically achievable third-party registrants for a deployment that intends to correct false assertions without -relying on a dominant single voter. +relying on a dominant single voter. Note that `N_voters >= 3` is a floor for a +healthy electorate, not a sufficient condition for correction on its own. The +model above assumes a symmetric split of revealed weight, under which the +against-side weight equals exactly `W / 2` regardless of `N_voters`: correction +always requires an honest-side *imbalance* (more revealed weight against than +for), not just a larger headcount. A deployment with three third-party voters +all revealing on the honest side will correct a false assertion; a deployment +where half reveal for the asserted outcome will not, regardless of how many +participants registered. ### Whale-capture check From 9b961915dbd83ee9b7c170d14b507b578ab01d87 Mon Sep 17 00:00:00 2001 From: Kayce10 Date: Sat, 29 Aug 2026 22:25:35 +0000 Subject: [PATCH 5/5] docs: fix threshold-comparison rationale in V2_BOND_SIZING The subtraction form (side_weight > W - side_weight) is used because integer division rounds down and would wrongly pass a side sitting exactly at the boundary on an odd W, not to avoid overflow. Doubling side_weight cannot overflow since it is bounded well below i128::MAX. Fixes the rationale to match lib.rs:1376-1378's own comment. --- docs/src/V2_BOND_SIZING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/V2_BOND_SIZING.md b/docs/src/V2_BOND_SIZING.md index d9d929e..68f5041 100644 --- a/docs/src/V2_BOND_SIZING.md +++ b/docs/src/V2_BOND_SIZING.md @@ -499,10 +499,10 @@ With your chosen parameters: where half the third parties side with each party. 3. Against-side weight: `base_bond x (1 + N_voters / 2)`. 4. Required threshold: strictly more than `W / 2`. The contract uses the - comparison `side_weight > W - side_weight` (equivalently `2 x side_weight > W`), - which avoids doubling overflow and handles both even and odd `W` correctly. - For an integer `W`, this means against-side weight must be at least - `floor(W / 2) + 1`. + comparison `side_weight > W - side_weight` rather than `side_weight > W / 2`: + integer division rounds down, which would wrongly pass a side sitting exactly + at the boundary on an odd `W`. For an integer `W`, this means against-side + weight must be at least `floor(W / 2) + 1`. If `N_voters` is small (e.g., 1), then `W = 3 x base_bond`, against-side weight is `1.5 x base_bond`, and the required threshold is `floor(3B / 2) + 1`; with