Skip to content

test(vault): exercise sweep/pause/upgrade lifecycle against the admin cool-off (#1125) - #1343

Open
Sam-Rytech wants to merge 1 commit into
CalloraOrg:mainfrom
Sam-Rytech:test/1125-sweep-lifecycle-admin-cooldown
Open

Sam-Rytech wants to merge 1 commit into
CalloraOrg:mainfrom
Sam-Rytech:test/1125-sweep-lifecycle-admin-cooldown

Conversation

@Sam-Rytech

Copy link
Copy Markdown
Contributor

Summary

execute_pause, execute_upgrade and execute_sweep share admin::guard, the only thing stopping an admin key from chaining pause + sweep + upgrade in one block once several proposals have matured. No running test covered back-to-back matured proposals or cancel/re-propose sequences. This PR adds that coverage from the public contract surface.

New tests — contracts/vault/src/test_timelock_cooldown.rs

The module is compiled under #[cfg(test)] and named *timelock*, so cargo test -p callora-vault timelock selects it.

Test What it proves
…sweep_then_pause_blocked_until_boundary After execute_sweep, a matured pause fails with AdminCooldownActive in the same block. The vault stays unpaused and the proposal is kept. It is still blocked 1 s before the boundary (admin_cooldown_remaining == 1) and succeeds exactly at it. get_last_critical_admin_action moves from sweep to pause with correct timestamps.
…pause_then_sweep_moves_no_funds_until_boundary The reverse order: the blocked sweep transfers nothing and keeps its proposal; after the cooldown the funds move and the action is recorded as sweep.
…upgrade_path_is_guarded_too A matured execute_upgrade after a pause is refused by the same guard, which runs before the WASM swap.
…failed_execution_does_not_arm_cooldown A sweep that fails with InsufficientBalance leaves get_last_critical_admin_action == None, and another action can run immediately.
…execute_pause_on_already_paused_vault_does_not_arm_cooldown The idempotent no-op path never arms the cool-off.
…cancel_sweep_is_idempotent_with_is_some_payload cancel_sweep with nothing pending emits false; with a proposal true; repeated false. Cancelling never arms the cool-off, and executing afterwards gives ProposalNotFound.
…cancel_and_repropose_restarts_timelock_and_respects_cooldown A re-proposal restarts execute_after (the old deadline now gives TimelockNotExpired), and a matured re-proposal is still blocked by an active cool-off until its boundary.

Acceptance criteria → tests

Criterion Tests
Second execute within cooldown fails with AdminCooldownActive sweep→pause, pause→sweep, upgrade path, re-propose
Execution after cooldown succeeds sweep→pause and pause→sweep (exactly at the boundary), re-propose
get_last_critical_admin_action reports the right symbol asserted after every execution, including None after failed and no-op executions
cancel_sweep with nothing pending emits a false payload …cancel_sweep_is_idempotent_with_is_some_payload

Required one-line fix

test_value_conservation.rs called env.events().all() without importing the soroban_sdk::testutils::Events trait. That made the entire callora-vault test target fail to compile on main, so no vault test could run, including the issue's validation command. This PR adds that import and changes no test logic.

Validation

cargo test -p callora-vault timelock
test test_timelock_cooldown::… ok   (7 new)
test result: ok. 9 passed; 0 failed     (lib, incl. existing timelock-named tests)
test result: ok. 3 passed; 0 failed     (timelock error-code tests)
  • rustfmt --check passes on the new file.
  • No production code is changed.

Note for maintainers

Now that the test target compiles again, the full cargo test -p callora-vault shows 2 pre-existing failures in test_value_conservation (*_without_settlement_returns_error_before_mutation). They were hidden by the compile error and are unrelated to the admin cool-off, so they are left for a separate fix.

Closes #1125

… cool-off (CalloraOrg#1125)

Adds contracts/vault/src/test_timelock_cooldown.rs (compiled; selected by
`cargo test -p callora-vault timelock`):
- two matured proposals executed back-to-back in either order
  (sweep->pause, pause->sweep): the second fails with AdminCooldownActive,
  moves no funds and keeps its proposal, stays blocked 1s before the
  boundary, and succeeds exactly at it
- execute_upgrade is refused by the same guard
- get_last_critical_admin_action reports the right symbol and timestamp
  after each execution
- a failed execution (InsufficientBalance) and the already-paused
  execute_pause no-op never arm the cool-off
- cancel_sweep is idempotent: payload false with nothing pending, true
  when a proposal exists, false again on repeat; cancelling never arms
  the cool-off
- cancel -> re-propose restarts the timelock and still respects the
  cool-off

Also imports the testutils `Events` trait in test_value_conservation.rs.
Without it the whole callora-vault test target failed to compile on main,
so no vault test (including these) could run. Import only; no test logic
changed.

Closes CalloraOrg#1125
@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@Sam-Rytech 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

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.

Exercise sweep lifecycle against admin cool-off

1 participant