Skip to content

feat: implement v2 symmetric freeze/cancel emergency mechanism - #89

Merged
collinsezedike merged 3 commits into
mainfrom
feat/v2-freeze-cancel
Aug 13, 2026
Merged

feat: implement v2 symmetric freeze/cancel emergency mechanism#89
collinsezedike merged 3 commits into
mainfrom
feat/v2-freeze-cancel

Conversation

@collinsezedike

Copy link
Copy Markdown
Collaborator

Summary

Implements #71: the symmetric freeze/cancel emergency mechanism for an already-active v2 round. Note the issue itself states this design "needs maintainer sign-off before merging" and was never specified in docs/src/V2_RESOLUTION.md; the one explicit open question in the issue (whether cancel_round should require a grace period after a pause starts) was resolved directly in conversation before implementing: instant is what's built here, since cancellation only ever runs before a terminal outcome locks, so there's no real "winner" to preempt, and any position that doesn't get to reveal in time still gets its full principal back through cancellation's no-forfeiture refund regardless.

  • set_paused_v2(paused): blocks new assert_outcome calls. Deliberately narrower than v1's pause: an already-active round's registration, reveal, resolution, settlement, and withdrawal all continue normally while paused, since blocking them would strand capital already locked into that round rather than protect it.
  • cancel_round(id): callable only while paused, and only while terminal_cause is still NotYetDecided (Pending, or Registration/Reveal with no strict majority reached yet). Refunds every already-funded position its exact principal, no forfeiture, no reward. Fails outright, not as a no-op, with RoundAlreadyDecided once terminal_cause is set by any means (a real outcome, or an earlier cancellation), making it structurally impossible for this call to alter an already-decided result.
  • A still-Pending cancellation refunds the asserter's bond directly, since no Resolution/Position exists yet at that phase. A Registration/Reveal cancellation instead sets a new TerminalCause::AdminCancelled and closes the round to Resolved; every position (including any that already revealed) then recovers its principal through the existing settle/withdraw path from [Feature] V2: implement settlement and forfeiture distribution #69/[Feature] V2: implement credit accrual and owner-authorized withdrawal #70, with no special-casing needed there: settlement_pool treats AdminCancelled as recipient_weight = eligible_total, so forfeited_pool is always 0 and every position is a recipient.
  • New RoundCancelled event, distinct from Resolved, so indexers can always tell a cancellation apart from a real outcome.

Test plan

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test pass locally
  • cargo build -p tholos --target wasm32v1-none --release and cargo build --workspace --target wasm32v1-none --release pass locally
  • mdbook build docs passes locally
  • CONTRACT.md updated if the public interface changed — not applicable, tholos-v2 isn't documented there yet (tracked separately)
  • scripts/testnet-smoke.sh run against testnet — not run; this only touches tholos-v2, which isn't deployed yet
  • What you manually verified: added 11 new tests covering set_paused_v2 (blocks new assertions, doesn't block an active round's full lifecycle through settlement/withdrawal), and cancel_round across all three cancellable phases (Pending direct refund, Registration with a third-party position, Reveal with one already-revealed and one never-revealed position, confirming neither gets a reward or forfeits anything), plus its failure modes (not paused, nonexistent assertion, already decided via strict majority/optimistic timeout/uncontested finalize/a prior cancellation).

@collinsezedike
collinsezedike merged commit bd9e809 into main Aug 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant