You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Documents every cross-contract invocation in the Vatix protocol so
developers can reason about call chains, authorization requirements, and
failure modes without reading all four contract sources.
OutcomeTokenContract::balance (read), plus mint/burn from reconcile_position_tokens
Trigger
Every trade and settlement attempt (guard check); admin-initiated repair
Purpose
Position (Market storage) and OutcomeToken balances are two ledgers that are supposed to always agree — a historical bug, partial upgrade, or manual admin mint/burn issued directly on the outcome-token contract can make them diverge. The guard reads both ledgers and refuses to proceed on mismatch instead of silently re-syncing
Auth required
Guard reads (balance) need no auth. reconcile_position_tokens requires the Market contract's stored admin
Failure behaviour
update_position/settle_position reject with ContractError::PositionTokenMismatch (after emitting PositionTokenMismatchDetected) when the two ledgers disagree for that user/market. batch_settle_positions/settle_positions_page skip the affected user rather than aborting the whole batch
Repair
MarketContract::reconcile_position_tokens(admin, market_id, user) mints/burns OutcomeToken balances to match Position (Position is the source of truth — see contracts/market/src/reconciliation.rs), emitting PositionTokensReconciled
Registration
Reuses the existing set_outcome_token_contract wiring — no separate registration step
update_position(user, market_id, yes_delta, no_delta, price)
→ OutcomeToken::balance(market_id, user, Yes|No) [parity check, both sides]
→ reject with PositionTokenMismatch if divergent, else proceed as in edge 1
settle_position(user, market_id) / batch_settle_positions / settle_positions_page
→ OutcomeToken::balance(market_id, user, Yes|No) [parity check]
→ reject (single) or skip (batch/page) with PositionTokenMismatch if divergent
reconcile_position_tokens(admin, market_id, user) [admin-gated]
→ OutcomeToken::mint / OutcomeToken::burn [bring balances back to Position]
Registering a resolution contract selects this challenge-based lifecycle as the
market's exclusive resolution mode. While the registration is present,
Market::resolve_market_threshold fails closed with
ResolutionNotFinalized; a threshold quorum therefore cannot bypass an open or
challenged candidate. Threshold resolution remains available only when no
resolution contract is registered. After finalize resolves the market through
the guarded single-signature callback, any later resolution attempt fails with
MarketAlreadyResolved.