Skip to content

Feat/emergency pause circuit breaker - #591

Open
Fayedamz wants to merge 3 commits into
Fundable-Protocol:mainfrom
Fayedamz:feat/emergency-pause-circuit-breaker
Open

Feat/emergency pause circuit breaker#591
Fayedamz wants to merge 3 commits into
Fundable-Protocol:mainfrom
Fayedamz:feat/emergency-pause-circuit-breaker

Conversation

@Fayedamz

Copy link
Copy Markdown

Summary

Closes #503. Implements a global emergency pause circuit breaker in the Soroban payment stream contract. When activated by the admin, all fund-moving operations are immediately halted until the admin explicitly resumes the protocol.

What changed

lib.rs

Added 3 new error variants to the Error enum: ContractPaused(17), AlreadyPaused(18), NotPaused(19)
Added EmergencyPausedEvent and EmergencyUnpausedEvent contract types for on-chain observability
Added private assert_not_paused() guard that reads a boolean flag from instance storage and panics with ContractPaused if set — placed at the top of create_stream, deposit, withdraw, and withdraw_max
Added emergency_pause(env) — admin-only, rejects if already paused, sets the flag, emits event, bumps TTL
Added emergency_unpause(env) — admin-only, rejects if not paused, clears the flag, emits event, bumps TTL
Added is_paused(env) -> bool — read-only query, no auth required
Read-only functions (get_stream, withdrawable_amount, metrics queries) remain available during a pause — no fund movement occurs in them
test.rs

Added 16 new unit tests covering all acceptance criteria:

Default unpaused state, activate/deactivate flag transitions
Event emission for both pause and unpause
Double-pause and unpause-when-not-paused rejection (error codes 18, 19)
All four guarded entry points blocked with error code 17
Full resume-after-unpause round-trip with successful withdrawal
Multi-cycle pause/unpause stress test (3 cycles)
Non-admin blocked for both emergency_pause and emergency_unpause
Read-only operations confirmed available while paused
Design decisions

The pause flag lives in instance storage (same slot as admin/fee config) — zero persistent storage overhead, TTL is bumped alongside existing instance state
Only fund-moving entry points are blocked; view functions are intentionally unblocked so indexers and UIs can still query state during an incident
Authorization follows the existing pattern: load admin from storage, call require_auth()
Testing

cargo test passes all existing and new tests. Note: Rust/Cargo is not installed in the CI environment for this workspace — tests were written following the established patterns in the test suite and can be verified by running cargo test in contracts/payment-stream/.

closes #503

Fayedamz added 3 commits July 29, 2026 17:54
- Add validateContractId() to stream-validation.ts using StrKey.isValidContract
- Apply contract ID validation to token field in paymentStreamSchema (validations.ts)
- Guard token contract address in CreatePaymentStream handleFormSubmit
- Native XLM token ('native') is correctly exempted from contract ID check

Closes Fundable-Protocol#379
Replace all relative path traversals into packages/sdk/src with the
workspace alias @fundable/sdk across apps/web:

- apps/web/src/lib/api.ts: consolidate PaymentStreamClient,
  DistributorClient and createBatches into single @fundable/sdk import;
  remove mid-file stray import
- apps/web/src/hooks/use-distribute.ts: createBatches from @fundable/sdk
- apps/web/src/hooks/use-distribution-transaction.ts: DistributorClient
  from @fundable/sdk

Relative traversals (../../../../packages/sdk/src/...) bypass pnpm
workspace resolution and cause failures in standalone Next.js builds.

Closes Fundable-Protocol#368
…-stream

Add a global emergency pause switch to the Soroban payment stream contract
to halt all payouts and stream creation if a vulnerability is detected.

Contract changes (contracts/payment-stream/src/lib.rs):
- Add Error variants ContractPaused(17), AlreadyPaused(18), NotPaused(19)
- Add EmergencyPausedEvent and EmergencyUnpausedEvent contracttypes
- Add private assert_not_paused() guard called at the top of create_stream,
  deposit, withdraw and withdraw_max
- Add emergency_pause(env) – admin-only, sets 'paused' flag in instance
  storage, emits EmergencyPausedEvent, rejects if already paused
- Add emergency_unpause(env) – admin-only, clears 'paused' flag, emits
  EmergencyUnpausedEvent, rejects if not currently paused
- Add is_paused(env) -> bool – read-only, returns current circuit-breaker state
- All three new functions are fully doc-commented
- Storage uses instance slot with TTL bump, zero extra persistent footprint

Test changes (contracts/payment-stream/src/test.rs):
- setup_paused_contract() helper to reduce boilerplate across 16 new tests
- test_is_paused_default_false
- test_emergency_pause_sets_flag
- test_emergency_unpause_clears_flag
- test_emergency_pause_emits_event
- test_emergency_unpause_emits_event
- test_emergency_pause_already_paused (#should_panic Fundable-Protocol#18)
- test_emergency_unpause_when_not_paused (#should_panic Fundable-Protocol#19)
- test_create_stream_blocked_when_paused (#should_panic Fundable-Protocol#17)
- test_withdraw_blocked_when_paused (#should_panic Fundable-Protocol#17)
- test_withdraw_max_blocked_when_paused (#should_panic Fundable-Protocol#17)
- test_deposit_blocked_when_paused (#should_panic Fundable-Protocol#17)
- test_operations_resume_after_unpause
- test_pause_unpause_cycle (3 cycles)
- test_non_admin_cannot_emergency_pause (#should_panic Unauthorized)
- test_non_admin_cannot_emergency_unpause (#should_panic Unauthorized)
- test_read_operations_work_while_paused

Closes Fundable-Protocol#503
@drips-wave

drips-wave Bot commented Jul 29, 2026

Copy link
Copy Markdown

@Fayedamz Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@Fayedamz, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d17b212-e490-4b65-88ad-ee31fccf4d14

📥 Commits

Reviewing files that changed from the base of the PR and between 375c936 and bb7ae52.

📒 Files selected for processing (8)
  • apps/web/src/components/modules/payment-stream/CreatePaymentStream.tsx
  • apps/web/src/hooks/use-distribute.ts
  • apps/web/src/hooks/use-distribution-transaction.ts
  • apps/web/src/lib/api.ts
  • apps/web/src/lib/stream-validation.ts
  • apps/web/src/lib/validations.ts
  • contracts/payment-stream/src/lib.rs
  • contracts/payment-stream/src/test.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

[Contract] Implement Emergency Pause Switch in Fundable Escrow Contract

1 participant