Skip to content

Emergency Circuit Breaker with Scoped Function Guards & Time-Bound Auto-Expiry #42

Closed

Description

@meshackyaro

Description

This issue aims to address the implementation of Emergency Circuit Breaker with Scoped Function Guards & Time-Bound Auto-Expiry.

The core objective is to: Add a shared pausability primitive across the escrow, reputation, and loyalty contracts that can halt specific classes of operation during an incident, always leaves user-fund-recovery paths open, and auto-expires so a pause can never become a permanent freeze.

By completing this feature, we will ensure that the GuildWorkman protocol maintains its high standards for security, usability, and decentralized logic. This issue requires careful attention to the Smart Contract architecture and adherence to the existing project conventions.

When picking up this issue, please ensure you document any new dependencies or architectural decisions made during development.

Component

Smart Contracts (Soroban)

Difficulty

🔴 Hard

Current state

None of the three contracts has any halt mechanism. If a bug or an exploit is discovered in escrow, the only options available today are "watch it drain" or "upgrade under fire" — and the upgrade path itself is still being built out in #16 / #27.

The design constraint that makes this more than a boolean flag: a pause must never trap user funds. Pausing create_appointment (stop new money entering) is safe; pausing cancel_appointment (stop refunds leaving) creates a hostage situation. Scoped guards plus a ledger-time expiry are what separate a circuit breaker from a rug pull.

Tasks

  • Review the existing Soroban workspace under soroban-contracts/contracts/
  • Implement the contract logic for: Emergency Circuit Breaker with Scoped Function Guards & Time-Bound Auto-Expiry
  • Define pause scopes rather than one global flag, so entry paths can be halted independently of exit/refund paths
  • Enforce that fund-recovery paths (cancel_appointment, dispute resolution, token burn/transfer of already-held balances) remain callable while paused, and document the reasoning
  • Implement ledger-time-bound auto-expiry with a maximum pause duration, so an unattended pause self-clears
  • Gate pause/unpause behind the admin/governance authority, keeping it consistent with the guard introduced in Upgradeable Contract Architecture with Storage Migration & Governance Guard #16 and the signer rotation in Governance signer rotation for the upgrade guard #27
  • Emit a clear signal on pause and unpause so off-chain monitoring can react (coordinate with the event work in the structured-events issue)
  • Add a dedicated Error variant for paused operations rather than reusing InvalidStatus
  • Write comprehensive unit and integration tests, including adversarial edge cases — non-admin pause attempts, refund-while-paused, and calls after expiry
  • Add caching for cargo dependencies in CI
  • Run cargo fmt --check and cargo clippy -- -D warnings
  • Run cargo test and soroban contract build to verify the optimized WASM build

Acceptance Criteria

  • Feature accurately implements the objective: Add a shared pausability primitive across the escrow, reputation, and loyalty contracts that can halt specific classes of operation during an incident, always leaves user-fund-recovery paths open, and auto-expires so a pause can never become a permanent freeze.
  • While paused, no new funds can enter escrow, and existing funds can still be recovered by their rightful owner — proven by test
  • A pause expires automatically at its deadline without requiring an admin transaction
  • Only the admin/governance authority can pause or unpause; a non-admin attempt fails with a distinct error
  • Any PR that introduces compiler or clippy warnings is automatically blocked
  • Contract logic is covered by tests exercising success, failure, and attack paths
  • Storage layout and authorization are documented and reviewed for safety
  • Code is properly reviewed and approved by codeowners

Estimated Time

2-3 days

Activity

  1. bbjiggy commented on Aug 19, 2026

    @bbjiggy
    Contributor

    Hi, I would like to take up this issue. Below is the proposed design, architectural plan, and testing strategy for implementing the Emergency Circuit Breaker with Scoped Function Guards & Time-Bound Auto-Expiry across the Soroban workspace.


    Architectural Design

    1. Shared Circuit Breaker Primitive

    To ensure uniform logic across escrow, reputation, and loyalty, I will introduce a shared pausable module inside the workspace's shared utilities/crates.

    Storage Data Structure:

    #[contracttype]
    pub enum PauseScope {
        CreateAppointment = 1 << 0,
        MintReputation    = 1 << 1,
        MintLoyalty       = 1 << 2,
        AllInbound        = 0xFFFFFFFF,
    }
    
    #[contracttype]
    pub struct PauseState {
        pub flags: u32,         // Bitmask for active pause scopes
        pub expires_at: u64,    // Ledger timestamp (env.ledger().timestamp())
    }
    
    #[contracttype]
    pub enum DataKey {
        PauseState,
        // ... existing keys
    }
    1. Time-Bound Auto-Expiry Logic

    Instead of relying solely on an administrative transaction to clear a pause state, every guard check evaluates the current ledger time:

    pub fn require_not_paused(env: &Env, scope: PauseScope) -> Result<(), ContractError> {
        if let Some(state) = env.storage().instance().get::<_, PauseState>(&DataKey::PauseState) {
            let current_time = env.ledger().timestamp();
            
            // Auto-expiry check: pause self-clears once deadline passes
            if current_time < state.expires_at && (state.flags & (scope as u32)) != 0 {
                return Err(ContractError::OperationPaused);
            }
        }
        Ok(())
    }
    1. Scoped Guards & Fund-Recovery Immunity
    • Halted Operations: create_appointment, mint_reputation, and new reward minting paths will invoke require_not_paused(env, Scope).
    • Fund-Recovery Exemption: Critical exit routes—such as cancel_appointment, dispute resolution distributions, and emergency token withdrawals—will explicitly omit the pause guard. This guarantees funds are never trapped, even during an active pause.
    • Max Pause Duration Cap: Admin execution of pause() will enforce a strict MAX_PAUSE_DURATION constant (e.g., 7 days) to prevent setting indefinite freeze states.
    1. Authorization & Event Integration
    • Governance Alignment: pause and unpause methods will require admin.require_auth(), remaining compatible with the signer rotation and guard patterns established in #16 and #27.
    • Structured Events:
    • PauseEvent { scopes: u32, expires_at: u64, caller: Address }
    • UnpauseEvent { scopes: u32, caller: Address }

    Work Plan & Tasks

    • Core Module: Implement Pausable state management and scope bitmask logic in the common smart contract crate.
    • Contract Integration: Integrate scoped guards into escrow, reputation, and loyalty entrypoints.
    • Error Handling: Declare ContractError::OperationPaused across contracts to distinguish pause halts from InvalidStatus.
    • CI Optimizations: Update GitHub Actions workflows to include actions/cache or Swatinem/rust-cache for Cargo target directories and dependencies.
    • Documentation: Document storage layouts, scope mappings, and auto-expiry logic in inline docs and repository architecture notes.

    Testing Strategy

    1. Scope Isolation Tests: Verify that halting CreateAppointment blocks new deposits while cancel_appointment executes without failure.
    2. Auto-Expiry Boundary Tests: Advance env.ledger().set_timestamp() past expires_at to confirm operations resume automatically without an unpause transaction.
    3. Adversarial / Auth Tests: Confirm non-admin calls to pause/unpause fail with authorization errors.
    4. CI Verification: Run local validations for cargo fmt --check, cargo clippy -- -D warnings, cargo test, and soroban contract build.
  2. Sparexonzy95 commented on Aug 19, 2026

    @Sparexonzy95

    I’m interested in taking this issue. I have experience working with Stellar/Soroban smart contracts and understand the security requirements around scoped pause guards, admin authorization, fund-recovery paths, and ledger-based auto-expiry. I’m confident I can implement this safely across the existing contracts, cover the critical success, failure, and adversarial cases with tests, and submit a solid PR within 2-3 days.

  3. grantfox-oss commented on Aug 19, 2026

    @grantfox-oss

    🦊 GrantFox — @bbjiggy has been assigned to this issue as part of the Third Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #42)
    2. Your PR will be reviewed by the workman-labs maintainers

    Good luck! Track your progress on GrantFox.

  4. grantfox-oss commented on Aug 20, 2026

    @grantfox-oss

    🎉 This issue has been marked as completed on GrantFox as part of the Third Campaign campaign!

    @bbjiggy's PR #46 was approved and merged by @meshackyaro.

    🏆 @bbjiggy: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (780 total points). Track your full progress on GrantFox.

    👏 Great work, @bbjiggy! Keep contributing to workman-labs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaigncontractsSmart contract (Soroban) workdifficulty: hard🔴 HardenhancementNew feature or requesthelp wantedExtra attention is neededpriority: high🔴 High priority — core / blocking

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions