Skip to content

Support independent pausing of deposits and deductions in the vault circuit-breaker #403

@greatest0fallt1me

Description

@greatest0fallt1me

Description

The vault's circuit-breaker is a single boolean (StorageKey::Paused) checked by require_not_paused (contracts/vault/src/lib.rs:1227), and pause/unpause (:535:557) flip it atomically. As documented in the module header (contracts/vault/src/lib.rs:2:11), a single pause() blocks both deposits and deductions. Operationally this is coarse: during an incident you often want to stop new spend (deductions) while still letting customers top up (deposit), or vice-versa.

This issue introduces independent pause switches for the deposit and deduction paths while preserving the existing all-or-nothing pause()/unpause() as a convenience that toggles both.

Requirements and context

Functional

  • Add two independent, admin/owner-gated switches with their own storage keys, e.g. PausedDeposits and PausedDeductions.
  • Add targeted entrypoints (admin/owner only, reusing require_admin_or_owner at contracts/vault/src/lib.rs:1234):
    • pause_deposits(caller) / unpause_deposits(caller)
    • pause_deductions(caller) / unpause_deductions(caller)
  • Enforce the granular flags: deposit (:572) checks the deposit flag; deduct (:637) and batch_deduct (:725) check the deduction flag. The existing require_not_paused should be refactored into path-specific guards.
  • Preserve backward compatibility: keep pause(caller) / unpause(caller) and is_paused() (:377). pause() sets both flags; is_paused() returns true when either is set (document this precisely). Add granular views is_deposits_paused() / is_deductions_paused().
  • withdraw / withdraw_to / distribute must remain allowed regardless of pause state (their current emergency-recovery policy, contracts/vault/src/lib.rs:852, :884, :911).
  • Emit events: deposits_paused / deposits_unpaused / deductions_paused / deductions_unpaused with caller as topic.

Non-functional / repo conventions

  • Update the module-level pause documentation block at the top of contracts/vault/src/lib.rs, plus EVENT_SCHEMA.md, the pause section of SECURITY.md, and docs/interfaces/vault.json.
  • Keep WASM within budget (scripts/check-wasm-size.sh).

Acceptance criteria

  • Four granular pause entrypoints plus two granular views implemented, all admin/owner-gated.
  • deposit blocked only by the deposit flag; deduct / batch_deduct blocked only by the deduction flag.
  • Legacy pause()/unpause() still set/clear both; is_paused() returns true iff either flag is set.
  • withdraw, withdraw_to, distribute succeed under any pause combination.
  • New events emitted and documented in EVENT_SCHEMA.md; SECURITY.md pause checklist updated.
  • Line coverage stays >= 95% (scripts/coverage.sh).

Suggested execution

1. Fork the repo and create a branch

git checkout -b feature/vault-independent-pause

2. Implement changes

  • contracts/vault/src/lib.rs — new storage keys, granular pause/unpause entrypoints + views, refactor require_not_paused into require_deposits_active / require_deductions_active, keep legacy pause/unpause as composite operations, emit events.
  • Update EVENT_SCHEMA.md, SECURITY.md, docs/interfaces/vault.json, and the module header doc block.

3. Write/extend tests in contracts/vault/src/test.rs (or a new test_pause.rs module):

  • deposits paused but deductions allowed, and the reverse;
  • legacy pause() blocks both; is_paused() true when only one flag is set;
  • withdraw/withdraw_to/distribute succeed while paused;
  • non-admin/non-owner callers rejected on every new entrypoint;
  • double-pause / unpause-when-not-paused error paths per flag.

4. Test and commit

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
./scripts/check-wasm-size.sh
./scripts/coverage.sh

Example commit message

feat(vault): independent pause switches for deposits and deductions

Guidelines

  • Coverage must stay >= 95% (scripts/coverage.sh), CI-enforced via .github/workflows/coverage.yml.
  • NatSpec-style /// docs on every new entrypoint; keep EVENT_SCHEMA.md, SECURITY.md, and docs/interfaces/vault.json in sync.
  • Backward compatible: legacy pause()/unpause()/is_paused() semantics preserved and documented.
  • Timeframe: 96 hours.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions