Skip to content

feat: admin force-resolve market with idempotency-key replay protection#810

Open
muffti123 wants to merge 1 commit into
Predictify-org:masterfrom
muffti123:feature/admin-force-resolve
Open

feat: admin force-resolve market with idempotency-key replay protection#810
muffti123 wants to merge 1 commit into
Predictify-org:masterfrom
muffti123:feature/admin-force-resolve

Conversation

@muffti123

Copy link
Copy Markdown
Contributor

Description

This PR adds an admin-only force_resolve_market entrypoint that allows an authorized primary admin to forcibly resolve a prediction market — regardless of its current state (Active, Ended, Disputed, etc.) — with full idempotency-key replay protection, mandatory reason enforcement, and a comprehensive audit trail.

Key Features

  • force_resolve_market — new public entrypoint accepting winning_outcomes: Vec<String>, reason: String, and idempotency_key: String
  • Idempotency-key replay protection via ForceResolveManager — each key is scoped per-market and permanently recorded after first use; duplicate keys are rejected with Error::ForceResolveReplayed (517)
  • Mandatory non-empty reason — enforces ForceResolveReasonEmpty (518) guard before any state mutation
  • Multi-outcome support — accepts a vector of winning outcomes (minimum 1, all must be valid market outcomes)
  • Full event emissionForceResolvedEvent (topic frc_rs), state-change event, and MarketForceResolved audit trail record
  • Payout distribution — auto-distributes winnings after force-resolve

Error Handling

Error Code Description
ForceResolveReplayed 517 Idempotency key already consumed for this market
ForceResolveReasonEmpty 518 Reason string is empty
InvalidInput 1205 Empty winning outcomes vector

Events

Event Topic Payload
ForceResolvedEvent frc_rs market_id, admin, outcome, reason, idempotency_key, timestamp

Testing

Comprehensive unit tests covering:

  • Happy path: active market, before-end-time, ended market
  • Input validation: invalid outcome, empty outcomes, empty reason, market not found
  • Idempotency: key replay rejection, different keys on same market, same key on different markets
  • Authorization: unauthorized caller rejection
  • Multi-outcome: multiple winning outcomes

Related Issues

Closes #179

- Add admin_force_resolve function to forcibly resolve markets in any state
- Implement idempotency-key replay protection per (admin, key) pair
- Add new DataKey::ForceResolveIdempotencyKey for persistent key storage
- Add ForceResolveReplayed error variant (517)
- Emit ForceResolvedEvent on successful force-resolve
- Add unit tests (force_resolve_tests.rs) and integration tests (tests/force_resolve_test.rs)
- Add place_bet max_fee_bps parameter for fee cap enforcement
- Add cancel_fee_update to FeeManager
- Update OracleValidationConfig with max_deviation_z_multiple and history_size
- Add AdminOverrideNonce DataKey for replay protection
- Reorganize FeeManager::update_fee_config signature (remove eta parameter)
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