Skip to content

[Security] Implement Circuit Breaker System with Emergency Stop, Graceful Shutdown, and Auto-Triggers #24

Description

@KarenZita01

Description

The contract currently has no formal emergency stop mechanism beyond the stub pause_resume_tests.rs. In the event of a critical vulnerability detection, security breach, or market emergency, there is no way to halt contract operations without upgrading the entire contract (which takes 48+ hours with timelock). A circuit breaker pattern with multiple trigger conditions and graded response levels is essential for production safety.

Emergency response gaps:

  • No emergency_stop() function to halt all state-changing operations
  • No automatic circuit breakers (e.g., detect anomalous trading volume, rapid price changes, large withdrawals)
  • No graceful_shutdown() that allows users to withdraw funds while blocking new operations
  • No rate_limit global mode for suspicion (not confirmed) vs active attack
  • No emergency roles (separate from admin) that can trigger pauses
  • No automatic unpause timeout to prevent accidental permanent lockout

Technical Context & Impact

  • Affected Components/Files: contracts/utility_contracts/src/lib.rs, contracts/utility_contracts/src/pause_resume_tests.rs, contracts/utility_contracts/src/pause_resume_fuzz_tests.rs
  • Impact: Critical Security - No way to stop protocol during active attack

Step-by-Step Implementation Guide

  1. Implement CircuitBreaker module: src/circuit_breaker.rs with BreakerState { Paused, RateLimited, GracefulShutdown, Active } and trigger levels
  2. Add emergency_stop(): Callable by emergency multi-sig (2-of-3) with immediate effect; emits EmergencyStopActivated(reason, triggered_by)
  3. Add automatic triggers: Implement check_circuit_breakers(env) called at start of every public function:
    • LargeWithdrawalBreaker: if single withdrawal > MAX_WITHDRAWAL, pause for that user
    • AbnormalVolumeBreaker: if 1h volume > 10x daily average, enter rate-limited mode
    • RapidPriceChangeBreaker: if price oracle reports >50% change in 1 ledger, pause oracle-dependent operations
  4. Implement graceful_shutdown(): Only existing positions can be closed; new streams/positions blocked; users can withdraw
  5. Add resume_after_timeout(): Auto-unpause after 24 hours unless emergency council extends
  6. Add rate_limit(env, user): In rate-limited mode, each user can execute max 1 transaction per N ledgers
  7. Wire into all public functions: Add require_contract_active() guard at the start of every state-changing function

Verification & Testing Steps

  1. Test emergency_stop: trigger -> call any state-changing function (should revert)
  2. Test graceful_shutdown: trigger -> user can withdraw -> user cannot create new stream
  3. Test automatic trigger: simulate large withdrawal -> verify circuit breaker activates for that user
  4. Test auto-unpause: activate emergency stop -> advance 24 hours -> operations resume automatically
  5. Test rate limit: activate rate-limited mode -> user attempts 2 transactions quickly (second should revert)
  6. Run full test suite: cargo test --package utility_contracts

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions