Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions stellar/GOVERNANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# GOVERNANCE.md — Wraith Protocol Contract Upgrade Policy

## Overview

This document describes the upgrade authority model for Wraith Protocol's Stellar (Soroban) contracts. It specifies which contracts are upgradeable, who controls upgrades, and under what conditions upgrades can occur.

## Contract Upgrade Classification

| Contract | Upgradeable | Admin | Notes |
|---|---|---|---|
| **stealth-sender** | ✅ Yes | Configurable at init | Core transfer logic; needs upgrade path for security patches |
| **stealth-registry** | ❌ No | N/A | Stateless registry; redeployment preferred over upgrade |
| **stealth-announcer** | ❌ No | N/A | Pure event emitter; no state to preserve |
| **wraith-names** | ❌ No | N/A | Name registry; redeployment with migration |

## Upgrade Authority Model (stealth-sender)

### Admin Role

- Set during `init()` as the second parameter
- Can be transferred to a new address via `set_admin()`
- Only the current admin can authorize upgrades or transfer admin rights

### Upgrade Mechanism

The admin can call `upgrade(new_wasm_hash)` to update the contract's WASM bytecode via Soroban's `deployer().update_current_contract_wasm()`. This:

- Replaces the contract logic while preserving all storage
- Requires admin authorization (`require_auth`)
- Fails if upgrade authority has been renounced

### Renounce Mechanism

The admin can permanently renounce upgrade authority via `renounce_upgrade_authority()`. After renouncement:

- No further upgrades are possible
- Admin cannot be changed
- This action is irreversible

### Security Properties

1. **Non-admin cannot upgrade** — `require_auth()` enforces admin signature
2. **Renounced authority cannot be re-acquired** — `Renounced` flag is one-way
3. **State preservation** — Soroban upgrades preserve instance storage
4. **No backdoor** — No way to bypass admin check or un-renounce

## Multisig Considerations

For production deployments, the admin address should be a multisig contract (e.g., Stellar native multisig or a custom threshold signer). The upgrade authority test suite verifies that:

- Single-signer admin cannot call upgrade without auth
- If admin is a multisig, threshold must be met (tested at multisig level)

## Test Coverage

See `stealth-sender/src/lib.rs` `#[cfg(test)]` module for adversarial tests covering:

- `test_non_admin_cannot_upgrade` — Auth enforcement
- `test_admin_can_upgrade` — Happy path
- `test_admin_can_renounce` — Renounce flow
- `test_cannot_renounce_twice` — Double-renounce prevention
- `test_cannot_upgrade_after_renounce` — Post-renounce upgrade blocked
- `test_cannot_set_admin_after_renounce` — Post-renounce admin change blocked
- `test_admin_can_change_admin` — Admin transfer
- `test_non_admin_cannot_change_admin` — Admin transfer auth enforcement
- `test_admin_change_preserves_announcer` — State preservation

## Mainnet Readiness

Before mainnet deployment:

- [ ] Deploy with multisig admin address
- [ ] Run full upgrade authority test suite
- [ ] Audit upgrade path with independent security reviewer
- [ ] Document admin key custody procedure
- [ ] Consider timelock for upgrades (add to contract if needed)
67 changes: 67 additions & 0 deletions stellar/PAUSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# PAUSE.md — Wraith Protocol Contract Pause Status

## Overview

This document describes the pause (circuit-breaker) posture for each Wraith Protocol Stellar contract. Pause functionality allows the admin to temporarily halt state-mutating operations in case of security incidents, while preserving read-only access.

## Contract Pause Status

| Contract | Pausable | Admin | Read-Only When Paused |
|---|---|---|---|
| **stealth-sender** | ✅ Yes | Configurable at init | ❌ Send/batch_send blocked |
| **wraith-names** | ✅ Yes | Configurable at init | ✅ resolve/name_of still work |
| **stealth-registry** | ❌ No | N/A | N/A (stateless, redeploy) |
| **stealth-announcer** | ❌ No | N/A | N/A (pure events) |

## Pause Behavior

### stealth-sender

**When paused:**
- `send()` → reverts with `ContractPaused`
- `batch_send()` → reverts with `ContractPaused`
- `upgrade()` → still works (admin may need to upgrade during incident)
- `set_admin()` → still works
- `pause()` / `unpause()` → still works (admin only)

**When unpaused:**
- All operations work normally

### wraith-names

**When paused:**
- `register()` → reverts with `ContractPaused`
- `update()` → reverts with `ContractPaused`
- `release()` → reverts with `ContractPaused`
- `resolve()` → ✅ still works (read-only)
- `name_of()` → ✅ still works (read-only)

**When unpaused:**
- All operations work normally

## Admin Control

Both pausable contracts require admin authorization for pause/unpause:
- `admin.require_auth()` enforced
- Admin set during `init()`
- No way to pause without admin signature

## Incident Response Playbook

1. **Detect** — Monitor for anomalous activity (unusual send volumes, unexpected name registrations)
2. **Pause** — Admin calls `pause()` on affected contract(s)
3. **Investigate** — Assess scope and impact of incident
4. **Fix** — If needed, upgrade contract (stealth-sender) or deploy fix
5. **Unpause** — Admin calls `unpause()` when safe to resume

## Testing

Pause tests are included in each contract's `#[cfg(test)]` module:

- `test_admin_can_pause` / `test_admin_can_unpause`
- `test_register_blocked_when_paused` (wraith-names)
- `test_update_blocked_when_paused` (wraith-names)
- `test_release_blocked_when_paused` (wraith-names)
- `test_resolve_works_when_paused` (wraith-names)
- `test_name_of_works_when_paused` (wraith-names)
- `test_register_works_after_unpause` (wraith-names)
Loading