Skip to content

Soroban Escrow: Add Emergency Pause (halt new intents; settle/refund always run) #98

Description

@0xdevcollins

Severity: HIGH — No Incident Response Without This

Problem

If a vulnerability is discovered post-deployment, there is currently no way to halt new lock() calls. Existing funds would be at risk while waiting for users to manually claim refunds.

Fix Required

Soroban HTLC Contract

Add an admin-controlled pause flag to DataKey:
```rust
pub enum DataKey {
Lock(BytesN<32>),
Admin,
Paused, // new
}
```

Add functions:

  • initialize(env, admin) — store admin address
  • pause(env) — admin only, set Paused = true
  • unpause(env) — admin only, set Paused = false
  • is_paused(env) -> bool

Add guard to lock() only:
```rust
if env.storage().instance().get::<DataKey, bool>(&DataKey::Paused).unwrap_or(false) {
panic_with_error!(&env, HTLCError::ContractPaused);
}
```

Do NOT pause withdraw() or refund() — users must always be able to recover funds.

EVM HTLC Contract

Use OpenZeppelin Pausable:
```solidity
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract HTLCEvm is ReentrancyGuard, Pausable, Ownable {
function lock(...) external nonReentrant whenNotPaused returns (bytes32) { ... }
function pause() external onlyOwner { _pause(); }
function unpause() external onlyOwner { _unpause(); }
}
```

Acceptance Criteria

  • lock() is blocked when paused on both Soroban and EVM
  • withdraw() and refund() work even when paused
  • Only admin/owner can pause and unpause
  • Paused and Unpaused events emitted
  • Tests: pause blocks lock, pause does not block withdraw/refund
  • Apply to Soroban Settlement contract settle() as well

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockchainSmart contracts and chain integrationsblockedsecuritySecurity fix or hardening

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions