Summary
prediction_market/src/lib.rs resolve_market has no validation that the winning side actually has bettors. A resolver can call resolve_market(market_id, true) (Yes wins) even when total_yes == 0 — all XLM in the pool (from the losing side) is then treated as "fees" and credited to AccumulatedFees.
Impact
- Direct fund theft: the resolver redirects all user bets to the platform fee pool. Users who bet on the correct side get 0 payout; users who bet on the losing side lose everything.
- No revert or warning: the market simply resolves and there is no mechanism for users to challenge it.
- Single point of failure: the resolver role is typically a governance multisig, but a compromised or malicious resolver can execute this at any time.
Why it's hard
- The resolver is trusted by design — the market needs an oracle to determine the outcome.
- Adding a "challenge window" requires rethinking the entire settlement lifecycle.
- Distinguishing "legitimate outcome" from "malicious sweep" is impossible on-chain without external price feeds.
Fix
- Add a minimum bettor count / minimum pool size check before allowing resolution.
- Require that the winning side has at least one bettor.
- Emit a
MarketResolved event with both sides' totals so off-chain monitors can flag suspicious resolutions.
- Add a dispute window before fees are claimable.
Summary
prediction_market/src/lib.rsresolve_markethas no validation that the winning side actually has bettors. A resolver can callresolve_market(market_id, true)(Yes wins) even whentotal_yes == 0— all XLM in the pool (from the losing side) is then treated as "fees" and credited toAccumulatedFees.Impact
Why it's hard
Fix
MarketResolvedevent with both sides' totals so off-chain monitors can flag suspicious resolutions.