docs: add full contract reference for tholos-v2 - #104
Conversation
Documents contracts/tholos-v2's public interface in docs/src/CONTRACT_V2.md, matching the structure and level of detail CONTRACT.md already gives v1: lifecycle diagram, every type, every public function with signer/return/error detail, the full Error enum, the event table, security notes, and persistent-storage TTL behavior. Every claim was cross-checked against contracts/tholos-v2/src/lib.rs as written, not restated from doc comments verbatim. Registers the new page in docs/src/SUMMARY.md so mdbook build picks it up. Fixes #<issue-number>
collinsezedike
left a comment
There was a problem hiding this comment.
One general note not tied to a single line: INTEGRATION.md's existing "Lifecycle at a glance" section fully duplicates this doc's lifecycle/function content, with no cross-reference either way. Worth linking one to the other so they don't silently drift.
| [*] --> Pending: assert_outcome | ||
| Pending --> Resolved: finalize<br/>(challenge window elapsed,<br/>uncontested) | ||
| Pending --> Registration: dispute | ||
| Registration --> Reveal: register deadline passes<br/>(lazily, on next register/reveal/resolve_outcome) |
There was a problem hiding this comment.
The diagram lists register as a trigger for the lazy Registration → Reveal transition, but register never calls open_reveal_phase. After the deadline it just returns Error::RegistrationClosed (see test_register_after_deadline_fails). Only reveal and resolve_outcome open reveal phase.
| Pending --> Resolved: finalize<br/>(challenge window elapsed,<br/>uncontested) | ||
| Pending --> Registration: dispute | ||
| Registration --> Reveal: register deadline passes<br/>(lazily, on next register/reveal/resolve_outcome) | ||
| Reveal --> Resolved: resolve_outcome<br/>(strict majority locked, or<br/>reveal deadline / full reveal reached) |
There was a problem hiding this comment.
This edge is mislabeled two ways. "Strict majority locked" doesn't by itself cause the phase transition, your own prose right below this diagram says phase stays Reveal after a majority locks. And reveal itself can also close Reveal → Resolved in the same call when it's the last outstanding weight, not just resolve_outcome.
| | `StrictMajorityFor` | Revealed weight agreeing with the asserted outcome exceeded half of the frozen eligible total `W`. | | ||
| | `StrictMajorityAgainst` | Revealed weight disagreeing exceeded half of `W`. | | ||
| | `OptimisticTimeout` | Neither side reached a strict majority before reveal closed; the originally asserted outcome stands by default. | | ||
| | `AdminCancelled` | Set only by `cancel_round`, on a `Registration`/`Reveal`-phase assertion with no terminal cause yet. Every funded position recovers its exact principal, no forfeiture, no reward. | |
There was a problem hiding this comment.
This row says AdminCancelled only applies to a Registration/Reveal-phase assertion, but cancel_round also handles a still-Pending assertion (refunding the asserter's bond directly). Your own Functions section for cancel_round describes that Pending path correctly, this table row contradicts it.
| | --- | --- | | ||
| | `AlreadyInitialized` | `initialize` called on a contract that's already set up. | | ||
| | `NotInitialized` | Called before `initialize`. | | ||
| | `AssertionNotFound` | No assertion (or, depending on call, resolution/position/credit) exists for the given id/address. | |
There was a problem hiding this comment.
AssertionNotFound doesn't cover a missing credit. get_credit returns 0 via unwrap_or(0), and withdraw returns NoCreditToWithdraw for a zero balance, not AssertionNotFound. Drop "credit" from this row.
| | `NotInitialized` | Called before `initialize`. | | ||
| | `AssertionNotFound` | No assertion (or, depending on call, resolution/position/credit) exists for the given id/address. | | ||
| | `InvalidBondAmount` | `base_bond` isn't positive, or exceeds `MAX_BOND_AMOUNT`. | | ||
| | `InvalidRegistrationDuration` | `registration_duration_secs` is zero or exceeds 7 days. | |
There was a problem hiding this comment.
These four "7 days" references (here, InvalidRevealDuration, InvalidChallengeWindow, and the initialize prose) point at three separately-defined constants in lib.rs that just happen to share a value today. Worth naming them individually, like the TTL section does with INSTANCE_BUMP_AMOUNT, so a future change to just one doesn't leave the others silently stale.
| tokens (`assert_outcome`, `finalize`, `dispute`, `register`, `withdraw`) | ||
| also holds a contract-wide reentrancy mutex (`ReentrancyGuard`) for the | ||
| duration of the transfer, via `enter_reentrancy_guard`/ | ||
| `exit_reentrancy_guard`. `reveal`, `resolve_outcome`, `settle`, and |
There was a problem hiding this comment.
This says cancel_round doesn't move tokens, but it does, it refunds the asserter's bond directly (same acquire/transfer/release pattern as withdraw) when the assertion is still Pending. It shouldn't be grouped with reveal/resolve_outcome/settle here.
| @@ -1,4 +1,4 @@ | |||
| # Summary | |||
| # Summary | |||
There was a problem hiding this comment.
This PR's diff shows this line changing even though nothing here should differ, it's a UTF-8 BOM getting silently added to the file start. Probably an editor artifact. Worth stripping before merge, it's noise unrelated to the PR's purpose.
|
Hey @Theophilus131, just checking in on this one, still no rush. There's a review with a few concrete mismatches to fix, let me know if anything's unclear or if you'd like a hand. |
What
Adds
docs/src/CONTRACT_V2.md, a complete reference forcontracts/tholos-v2'spublic interface — types, every function, the full
Errorenum, the eventtable, security notes, and persistent-storage TTL behavior — in the same
structure
CONTRACT.mdalready uses for v1.Why
v1 has full reference docs; v2 only had a lightweight lifecycle table in
INTEGRATION.md(signatures + one-liners, no error variants, no eventtable, no security/TTL notes) even though v2's lifecycle
(
assert_outcome→withdraw, plusset_paused_v2/cancel_round) is nowfully implemented. This closes that documentation gap.
Structure choice
Went with a separate
CONTRACT_V2.md(option 1 in the issue) rather thanextending
CONTRACT.mdwith a v2 section — v2's interface is large enough(11 functions, 36 errors, 12 events) that folding it into the existing
296-line v1 doc would make both harder to scan. Registered under
docs/src/SUMMARY.mdas a nested entry under the existing v1 "ContractReference" item.
Verification
Every function signature, error variant, event field, and behavioral claim
was checked line-by-line against
contracts/tholos-v2/src/lib.rs(notjust copied from doc comments) while writing this. In particular:
get_resolution/get_positionboth surfaceAssertionNotFoundfor amissing record (not a dedicated error), matched from the source.
settleandwithdrawfetchAssertionV2beforeResolutionand useNotResolved/NoCreditToWithdrawspecifically for theUncontestedFinalizecase, which never has aResolution— documentedas such rather than assumed.
PhaseV2::Reveal/terminal_causedistinction (a majority canlock while
phasestaysReveal) is called out explicitly, since it'seasy to get wrong from the type alone.
Checklist
docs/src/CONTRACT_V2.mdadded, same structure asCONTRACT.mddocs/src/SUMMARY.mdupdated somdbook buildincludes the new pagecontracts/tholos-v2/src/lib.rs, not restatedfrom doc comments