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
13 changes: 13 additions & 0 deletions stellar/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions stellar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"bench",
"wraith-asset-policy",
"wraith-metrics",
"contracts/governance",
]
resolver = "2"

Expand Down
69 changes: 69 additions & 0 deletions stellar/GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,75 @@ cargo test upgrade_auth --workspace

These tests run on every PR via CI and serve as living documentation of the governance model.

---

## On-Chain Governance PoC (`contracts/governance/`)

**Status: PROOF OF CONCEPT — NOT PRODUCTION READY**

`contracts/governance/` implements a minimal on-chain governance flow (propose → vote → execute) gated by token-weighted quorum. It was built to validate the architectural shape before committing the roadmap to replacing the multisig upgrade authority.

### How it works

1. **Init** — deployer sets the voting token address, absolute quorum threshold, voting period (ledgers), and timelock delay (ledgers).
2. **Propose** — any token holder creates a proposal specifying a target contract, function symbol, and raw argument bytes.
3. **Vote** — token holders vote for or against. Weight = token balance at vote time. One vote per address per proposal.
4. **Execute** — after the voting window closes and the timelock elapses, anyone may execute if:
- Total votes cast ≥ quorum
- `for_votes > against_votes`
5. **Cancel** — admin can cancel anytime; anyone can cancel a failed-quorum proposal after voting ends.

### Design decisions

| Decision | Choice | Rationale |
|---|---|---|
| **Quorum model** | Absolute token threshold | Simpler to reason about than percentage-based; avoids supply-dependent edge cases. The PoC uses a fixed `i128`. |
| **Voting weight** | Snapshot at vote time | No delegation, no checkpointing. A voter's balance is read when `vote()` is called. This is the simplest correct approach for a PoC. |
| **Proposal args** | Raw `Bytes` forwarded to target | Keeps the governance contract agnostic to the target function signature. The execution call passes the bytes as a single argument — the target must accept `Bytes`. A production system would need proper ABI encoding/decoding. |
| **Timelock** | Ledger-count delay after voting ends | Prevents instant execution; gives token holders time to exit if they disagree with a passed proposal. |
| **Admin role** | Hardcoded single address | Deliberately centralised for the PoC. A production system must either remove this role or make it a governance-controlled multisig. |
| **Event scheme** | `(action, proposal_id)` as topics | Matches the Wraith Stellar event convention. |

### Design decisions rejected

| Rejected | Why |
|---|---|
| **Percentage-based quorum** | Adds `total_supply` dependency; the token contract may not expose supply in a cheap way. Absolute threshold is simpler and sufficient for the PoC. |
| **Vote delegation** | Adds complexity (delegation chain, delegation expiry) with no immediate benefit for proving the flow shape. Can be added later. |
| **Multiple proposal types** | The PoC only supports `target.function(args)`. In production we'd want typed actions (upgrade contract, set fee, pause, etc.) with domain-specific validation. |
| **On-chain discussion / rationale** | Out of scope — off-chain forums are a better fit for discussion. |
| **Quadratic voting** | Interesting but overengineered for a PoC. Token-weighted voting is the simplest baseline. |
| **ZKP-based private voting** | Desirable for privacy, but orthogonal to proving the governance flow. |
| **Governor Bravo fork** | The EVM Governor pattern (Compound/Zora) is battle-tested but relies on EVM-specific primitives (delegatecall, storage slots). The Soroban equivalent would look very different. We chose a native Soroban design from scratch. |

### Known limitations (PoC)

- **Admin is a single address** — the very centralisation this PoC aims to eventually replace. The contract's `cancel` function gives the admin emergency override even for passed proposals.
- **No vote-weight checkpointing** — a voter can transfer tokens after voting and still have their original weight counted. A production system would snapshot at proposal start.
- **No proposal cancellation by proposer** — only admin can cancel during voting. The proposer should be able to withdraw their own proposal.
- **Raw `Bytes` arguments** — the execution call is a single-argument `invoke_contract` with no type safety. A production system would use typed action structs.
- **No minimum proposal threshold** — anyone can propose. In production, a token minimum (e.g. 1% of quorum) prevents spam.
- **No upgrade authority integration** — this contract does not yet hold the upgrade keys for `stealth-sender`, `wraith-names`, or any other contract. That integration is the next step.
- **No emergency pause** — the PoC has no circuit breaker. Production governance should include a pausable module.
- **Single token** — only one voting token is supported. Production may need multi-token or NFT-weighted voting.

### Path to production

1. Remove the single-admin role and replace with governance-controlled upgrade authority.
2. Snapshot voting weights at proposal creation time.
3. Add typed action structs with domain-specific validation for each contract.
4. Add minimum proposal threshold.
5. Integrate with the `pausable` module.
6. Add support for multiple voting tokens / delegation.
7. Formal audit before mainnet deployment.

### Running the PoC tests

```bash
cd stellar
cargo test --package governance
```

## Implementation Checklist
The following should be filed as follow-up issues with the `Stellar Wave` label:
- [ ] Create issue: "Implement 3-of-5 multisig on Stellar for mainnet admin"
Expand Down
14 changes: 14 additions & 0 deletions stellar/contracts/governance/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "governance"
version = "0.1.0"
edition = "2021"
description = "PoC on-chain governance for Wraith Protocol — NOT PRODUCTION READY"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
soroban-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Loading
Loading