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
- Implement
CircuitBreaker module: src/circuit_breaker.rs with BreakerState { Paused, RateLimited, GracefulShutdown, Active } and trigger levels
- Add
emergency_stop(): Callable by emergency multi-sig (2-of-3) with immediate effect; emits EmergencyStopActivated(reason, triggered_by)
- 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
- Implement
graceful_shutdown(): Only existing positions can be closed; new streams/positions blocked; users can withdraw
- Add
resume_after_timeout(): Auto-unpause after 24 hours unless emergency council extends
- Add
rate_limit(env, user): In rate-limited mode, each user can execute max 1 transaction per N ledgers
- Wire into all public functions: Add
require_contract_active() guard at the start of every state-changing function
Verification & Testing Steps
- Test emergency_stop: trigger -> call any state-changing function (should revert)
- Test graceful_shutdown: trigger -> user can withdraw -> user cannot create new stream
- Test automatic trigger: simulate large withdrawal -> verify circuit breaker activates for that user
- Test auto-unpause: activate emergency stop -> advance 24 hours -> operations resume automatically
- Test rate limit: activate rate-limited mode -> user attempts 2 transactions quickly (second should revert)
- Run full test suite:
cargo test --package utility_contracts
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:
emergency_stop()function to halt all state-changing operationsgraceful_shutdown()that allows users to withdraw funds while blocking new operationsrate_limitglobal mode for suspicion (not confirmed) vs active attackTechnical Context & Impact
contracts/utility_contracts/src/lib.rs,contracts/utility_contracts/src/pause_resume_tests.rs,contracts/utility_contracts/src/pause_resume_fuzz_tests.rsStep-by-Step Implementation Guide
CircuitBreakermodule:src/circuit_breaker.rswithBreakerState { Paused, RateLimited, GracefulShutdown, Active }and trigger levelsemergency_stop(): Callable by emergency multi-sig (2-of-3) with immediate effect; emitsEmergencyStopActivated(reason, triggered_by)check_circuit_breakers(env)called at start of every public function:LargeWithdrawalBreaker: if single withdrawal > MAX_WITHDRAWAL, pause for that userAbnormalVolumeBreaker: if 1h volume > 10x daily average, enter rate-limited modeRapidPriceChangeBreaker: if price oracle reports >50% change in 1 ledger, pause oracle-dependent operationsgraceful_shutdown(): Only existing positions can be closed; new streams/positions blocked; users can withdrawresume_after_timeout(): Auto-unpause after 24 hours unless emergency council extendsrate_limit(env, user): In rate-limited mode, each user can execute max 1 transaction per N ledgersrequire_contract_active()guard at the start of every state-changing functionVerification & Testing Steps
cargo test --package utility_contracts