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
[CRITICAL] No pause/circuit-breaker mechanism — cannot halt system in emergency
Summary
None of the four contracts has a pause or circuit-breaker function. In the event of a critical vulnerability (e.g., issue #1, #3, #27), there is no way to halt betting, claims, or withdrawals while a fix is deployed. The only recourse is a full upgrade (issue #5), which itself is irreversible and requires a trusted admin.
This means:
A discovered exploit cannot be contained — funds continue to flow until the upgrade is deployed.
Exploits propagate unchecked: An attacker can continue exploiting the vulnerability across many blocks/users until the upgrade is deployed. There is no "cooling off" period.
No emergency response: Unlike traditional financial systems that have circuit breakers to halt trading during volatility, this system has no equivalent mechanism.
Researcher reports to team, team needs 48 hours to prepare and test a fix
During those 48 hours, any user can cancel a market and trigger the fee theft
Funds drain continuously across all cancelled markets
No way to stop the bleeding — no pause, no circuit breaker
Team must rush the fix, risking incomplete or buggy deployment
Or team decides to live with the bug, accepting ongoing fund loss
Why It's Hard to Fix
Adding a pause mechanism requires addressing several intertwined problems:
(a) Which functions to pause?: Should place_bet, claim, resolve_market, cancel_market, withdraw_fees all be pauseable individually? Or a global system pause that stops everything?
(c) Pause reentrancy: If the system is paused mid-transaction, what happens to the pending operation? Does it revert? Does it complete? Partial states can leave the system in an inconsistent state.
(a) Global pause flag: Single bool paused state checked at the start of every state-altering function. Simple but requires modifying every function.
(b) Per-function pause flags: Each critical function has its own pause flag. More granular but requires more storage and checks.
(c) Emergency withdrawal path: Instead of a full pause, add a function to withdraw all funds to a safe address in an emergency. Still requires trust in the withdrawer.
(d) Timed pause with governance override: Pause for a fixed duration (e.g., 24 hours) during which governance can vote to resume or extend. Adds complexity but provides a defined window.
Suggested Triage
This is a system safety issue. The absence of a circuit breaker is a fundamental design gap. Possible approaches:
(a) Add global pause flag: simplest to implement. Add a paused bool to each contract, checked at the start of every external-call-prone function. Admins can pause/resume. Requires modifying ~200+ function calls across 4 contracts.
(b) Add emergency withdrawal: Instead of pausing, add a function emergency_withdraw_all(recipient) that transfers all contract XLM to a specified address. More targeted but still requires trust.
(c) Multi-sig controlled pause: Require M-of-N signatures to pause, reducing risk of single-admin compromise. More complex UX but more secure.
(d) Pause + events + governance: Add pause mechanism + events to notify users + governance process for emergency decisions. Most robust but heaviest implementation.
This issue is marked CRITICAL because it means there is no mechanism to contain or halt exploits in progress. Any critical vulnerability discovered in the contract code will continue to drain funds unchecked until an upgrade is deployed, and the upgrade mechanism itself has vulnerabilities (issue #5) that could be exploited to remove or bypass the pause.
[CRITICAL] No pause/circuit-breaker mechanism — cannot halt system in emergency
Summary
None of the four contracts has a pause or circuit-breaker function. In the event of a critical vulnerability (e.g., issue #1, #3, #27), there is no way to halt betting, claims, or withdrawals while a fix is deployed. The only recourse is a full
upgrade(issue #5), which itself is irreversible and requires a trusted admin.This means:
The Missing Feature
No contract in the system implements:
pauseflag oris_pausedstatepause()function callable by adminresume()function to restart operationspaused()query function to check statusWhy It's Critical
No containment capability: If a critical bug is discovered (e.g., the cancel_market fee theft in issue Systemic accounting & state-invariant violation across prediction_market ↔ referral_registry ↔ leaderboard — fee theft, leaderboard displacement, and unbounded inflation #1, the reentrancy in issue fix(leaderboard): count bonus awards in total_bets #27, or the empty-side sweep in issue [CRITICAL] resolve_market lets a resolver sweep the entire pool to fees by resolving to the empty side — griefing / fund theft #3), there is no way to stop the bleeding while a fix is prepared and tested.
Exploits propagate unchecked: An attacker can continue exploiting the vulnerability across many blocks/users until the upgrade is deployed. There is no "cooling off" period.
No emergency response: Unlike traditional financial systems that have circuit breakers to halt trading during volatility, this system has no equivalent mechanism.
Combined with no events (issue [HIGH] No event emission anywhere — off-chain indexers, UIs, and auditors cannot track state transitions #7): Even if a pause mechanism existed, there's no event infrastructure to notify users that the system was paused and then resumed.
Combined with upgrade vulnerability (issue [CRITICAL] upgrade() allows arbitrary WASM replacement with no timelock, delay, or multi-sig — single compromised admin key = total loss #5): If the admin key is compromised, the attacker can upgrade the contract to remove any pause mechanism that was added, or upgrade to a malicious version.
Attack Scenario: Unchecked Exploit Propagation
Why It's Hard to Fix
Adding a pause mechanism requires addressing several intertwined problems:
(a) Which functions to pause?: Should
place_bet,claim,resolve_market,cancel_market,withdraw_feesall be pauseable individually? Or a global system pause that stops everything?(b) Who can pause?: The admin? A multi-sig? A governance contract? If the admin is compromised (issue [CRITICAL] upgrade() allows arbitrary WASM replacement with no timelock, delay, or multi-sig — single compromised admin key = total loss #5), the pause can be bypassed.
(c) Pause reentrancy: If the system is paused mid-transaction, what happens to the pending operation? Does it revert? Does it complete? Partial states can leave the system in an inconsistent state.
(d) User notification: How do users know the system is paused? No events (issue [HIGH] No event emission anywhere — off-chain indexers, UIs, and auditors cannot track state transitions #7) means no way to inform users. They might keep trying operations that fail, or worse, not try and lose money without understanding why.
(e) Upgrade resistance: If the pause is implemented in the current code version, an attacker with admin key access (issue [CRITICAL] upgrade() allows arbitrary WASM replacement with no timelock, delay, or multi-sig — single compromised admin key = total loss #5) could upgrade to a version without the pause mechanism.
Possible Implementations
(a) Global pause flag: Single
boolpaused state checked at the start of every state-altering function. Simple but requires modifying every function.(b) Per-function pause flags: Each critical function has its own pause flag. More granular but requires more storage and checks.
(c) Emergency withdrawal path: Instead of a full pause, add a function to withdraw all funds to a safe address in an emergency. Still requires trust in the withdrawer.
(d) Timed pause with governance override: Pause for a fixed duration (e.g., 24 hours) during which governance can vote to resume or extend. Adds complexity but provides a defined window.
Suggested Triage
This is a system safety issue. The absence of a circuit breaker is a fundamental design gap. Possible approaches:
(a) Add global pause flag: simplest to implement. Add a
pausedbool to each contract, checked at the start of every external-call-prone function. Admins can pause/resume. Requires modifying ~200+ function calls across 4 contracts.(b) Add emergency withdrawal: Instead of pausing, add a function
emergency_withdraw_all(recipient)that transfers all contract XLM to a specified address. More targeted but still requires trust.(c) Multi-sig controlled pause: Require M-of-N signatures to pause, reducing risk of single-admin compromise. More complex UX but more secure.
(d) Pause + events + governance: Add pause mechanism + events to notify users + governance process for emergency decisions. Most robust but heaviest implementation.
This issue is marked CRITICAL because it means there is no mechanism to contain or halt exploits in progress. Any critical vulnerability discovered in the contract code will continue to drain funds unchecked until an upgrade is deployed, and the upgrade mechanism itself has vulnerabilities (issue #5) that could be exploited to remove or bypass the pause.