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
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.
Description
The vault's circuit-breaker is a single boolean (
StorageKey::Paused) checked byrequire_not_paused(contracts/vault/src/lib.rs:1227), andpause/unpause(:535–:557) flip it atomically. As documented in the module header (contracts/vault/src/lib.rs:2–:11), a singlepause()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
PausedDepositsandPausedDeductions.require_admin_or_owneratcontracts/vault/src/lib.rs:1234):pause_deposits(caller)/unpause_deposits(caller)pause_deductions(caller)/unpause_deductions(caller)deposit(:572) checks the deposit flag;deduct(:637) andbatch_deduct(:725) check the deduction flag. The existingrequire_not_pausedshould be refactored into path-specific guards.pause(caller)/unpause(caller)andis_paused()(:377).pause()sets both flags;is_paused()returnstruewhen either is set (document this precisely). Add granular viewsis_deposits_paused()/is_deductions_paused().withdraw/withdraw_to/distributemust remain allowed regardless of pause state (their current emergency-recovery policy,contracts/vault/src/lib.rs:852,:884,:911).deposits_paused/deposits_unpaused/deductions_paused/deductions_unpausedwithcalleras topic.Non-functional / repo conventions
contracts/vault/src/lib.rs, plusEVENT_SCHEMA.md, the pause section ofSECURITY.md, anddocs/interfaces/vault.json.scripts/check-wasm-size.sh).Acceptance criteria
depositblocked only by the deposit flag;deduct/batch_deductblocked only by the deduction flag.pause()/unpause()still set/clear both;is_paused()returnstrueiff either flag is set.withdraw,withdraw_to,distributesucceed under any pause combination.EVENT_SCHEMA.md;SECURITY.mdpause checklist updated.scripts/coverage.sh).Suggested execution
1. Fork the repo and create a branch
2. Implement changes
contracts/vault/src/lib.rs— new storage keys, granular pause/unpause entrypoints + views, refactorrequire_not_pausedintorequire_deposits_active/require_deductions_active, keep legacypause/unpauseas composite operations, emit events.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 newtest_pause.rsmodule):pause()blocks both;is_paused()true when only one flag is set;withdraw/withdraw_to/distributesucceed while paused;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.shExample commit message
Guidelines
scripts/coverage.sh), CI-enforced via.github/workflows/coverage.yml.///docs on every new entrypoint; keepEVENT_SCHEMA.md,SECURITY.md, anddocs/interfaces/vault.jsonin sync.pause()/unpause()/is_paused()semantics preserved and documented.