feat: implement v2 PolicySnapshot and versioned assertion state - #79
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New crate contracts/tholos-v2, a wholly separate contract from v1 (never upgraded in place, blue/green migration per V2_RESOLUTION.md). This PR implements #64's scope only: the immutable PolicySnapshotV2 pinned at assertion creation, and the AssertionV2 record it lives on.
initialize: pins deployment-wide defaults (token, base_bond, registration/reveal durations, anti-sniping params, position/weight bounds) into aPolicySnapshotV2, validated and stored once.min_resolution_bondalways equalsbase_bond(a cheaper minimum would let a third party break an asserter/disputer tie for a fraction of what they risked); bounded anti-sniping extension capped by a hard maximum.AssertionV2stores the pinned policy, its hash, phase, and (once resolved)terminal_cause/final_outcomedirectly on the assertion, not only in events.get_policy/get_assertion: read-only lookups.create_pending_assertion: private helper building/storing aPendingAssertionV2with a freshly pinned policy, not yet wired to a public entrypoint ([Feature] V2: implement bonded assertion posting #65 adds the real, bond-transferringassert_outcomeon top of it) or moving any tokens. Marked#[allow(dead_code)]with a comment pointing at [Feature] V2: implement bonded assertion posting #65, which removes the allow.One real SDK finding worth flagging for later v2 issues: soroban-sdk 26.1.0's
contracttypederive doesn't generate an XDRScValconversion forOption<EnumType>(onlyOptionof built-in types likeAddress/boolwork), soAssertionV2failed to compile withterminal_cause: Option<TerminalCause>. Worked around with aTerminalCause::NotYetDecidedsentinel variant instead ofNone, documented inline. Worth remembering for #66-#71, which will define more enums.Also fixed a real bug caught by testing, not by design:
initialize's validation order madeInvalidMaxTotalWeight's zero-case structurally unreachable (max_position <= max_total_weightalways failed first whenmax_total_weightwas 0). Reordered so total-weight bounds are checked before the position-relative check.Closes #64
Test plan
cargo fmt --check,cargo clippy --workspace --all-targets --locked -- -D warnings,cargo test --workspace --lockedall pass (67 v1 + 21 v2 + 2 integration-example tests)cargo build -p tholos-v2 --target wasm32v1-none --release --lockedsucceedsmdbook buildsucceedsErrorvariant has a dedicated test triggering it