Skip to content

feat(governance): add proposal-based weighted-vote governance for adm… - #273

Merged
wagmiiii merged 1 commit into
accensa:mainfrom
DooseWayo:feat/governance-multisig
Aug 30, 2026
Merged

feat(governance): add proposal-based weighted-vote governance for adm…#273
wagmiiii merged 1 commit into
accensa:mainfrom
DooseWayo:feat/governance-multisig

Conversation

@DooseWayo

Copy link
Copy Markdown

…in roles

Adds a new governance contract that closes the single-admin-key SPOF on ReceiptAnchor's merchant role: a fixed set of weighted members propose a call, vote on it over a bounded window, and once "yes" weight clears a configured quorum and outweighs "no", anyone can execute it. No change to the governed contract is needed — the host's own self-authorization rule (a contract's require_auth() on its own address auto-succeeds when it is the direct caller) carries the authority through when Governance calls into ReceiptAnchor's existing merchant-gated functions, the same mechanism already used for a MultisigAccount admin.

ReceiptAnchor has no upgrade entry point, and docs/ADR-003-upgradeability.md (accepted) forbids adding one without reopening that ADR, so this wrapper gates only the admin surface that actually exists today (set_min_anchor_interval, anchor_batch, prune_batches) rather than introducing upgrade authority.

Storage is kept small on purpose: each member's weight is its own persistent entry, per-voter "already voted" markers live in temporary storage so they expire with the voting window on their own, and a resolved proposal's calldata can be reclaimed immediately via prune_proposal instead of waiting on archival.

Also fixes two pre-existing, unrelated build breaks discovered while wiring up governance's own tests, both required just to get cargo build / cargo test working across the workspace again:

  • receipt-anchor and refund-vault Cargo.toml declared their optional budget_macros dependency under [dev-dependencies], which Cargo disallows (optional dev-dependencies are not permitted); moved it to [dependencies], still gated by the budget-assert feature and only referenced from a #[cfg(test)] module, so it never links into a real build.
  • receipt-anchor's test_shared_vectors_cover_required_edge_cases used the bare Vec identifier, which resolves to soroban_sdk::Vec (imported at the top of the file) instead of std's Vec, and doesn't implement FromIterator<&str>; qualified it as std::vec::Vec explicitly.

Note: contracts/refund-vault/src/lib.rs has a separate, still-unfixed issue — add_oracle (added in #262) is missing its body/closing brace and currently fails to compile at all. Left alone here since it's unrelated to this change and its intended whitelist-insertion logic isn't specified anywhere I could find.

Summary

Provide a brief summary of the changes in this pull request and the problem being solved.

Contract Change Safety Checklist

Please verify that your changes adhere to contract stability requirements:

  • Event Shapes: Does this PR modify event topic tuples or data shapes? (Breaking change per docs/EVENTS.md)
  • Storage Layout: Does this PR change storage keys or layout? (Assessed for archival & migration risks)
  • Error Variants: Does this PR add or renumber contract error codes? (Client-visible breaking change)
  • Changelog: Has a corresponding entry been added to CHANGELOG.md?
  • Deployments: Has any impact on deployed contracts or DEPLOYMENTS.md been documented?
  • Verification: Has this change been tested locally (cargo test) and/or exercised on Soroban testnet?

Related Issues

Closes #
Closes #130
Closes #131
Closes #132
Closes #133

…in roles

Adds a new `governance` contract that closes the single-admin-key SPOF on
ReceiptAnchor's merchant role: a fixed set of weighted members propose a
call, vote on it over a bounded window, and once "yes" weight clears a
configured quorum and outweighs "no", anyone can execute it. No change to
the governed contract is needed — the host's own self-authorization rule
(a contract's require_auth() on its own address auto-succeeds when it is
the direct caller) carries the authority through when Governance calls
into ReceiptAnchor's existing merchant-gated functions, the same mechanism
already used for a MultisigAccount admin.

ReceiptAnchor has no upgrade entry point, and docs/ADR-003-upgradeability.md
(accepted) forbids adding one without reopening that ADR, so this wrapper
gates only the admin surface that actually exists today
(set_min_anchor_interval, anchor_batch, prune_batches) rather than
introducing upgrade authority.

Storage is kept small on purpose: each member's weight is its own
persistent entry, per-voter "already voted" markers live in temporary
storage so they expire with the voting window on their own, and a
resolved proposal's calldata can be reclaimed immediately via
prune_proposal instead of waiting on archival.

Also fixes two pre-existing, unrelated build breaks discovered while
wiring up governance's own tests, both required just to get `cargo build`
/ `cargo test` working across the workspace again:
- receipt-anchor and refund-vault Cargo.toml declared their optional
  `budget_macros` dependency under [dev-dependencies], which Cargo
  disallows (optional dev-dependencies are not permitted); moved it to
  [dependencies], still gated by the `budget-assert` feature and only
  referenced from a #[cfg(test)] module, so it never links into a real
  build.
- receipt-anchor's test_shared_vectors_cover_required_edge_cases used the
  bare `Vec` identifier, which resolves to soroban_sdk::Vec (imported at
  the top of the file) instead of std's Vec, and doesn't implement
  FromIterator<&str>; qualified it as std::vec::Vec explicitly.

Note: contracts/refund-vault/src/lib.rs has a separate, still-unfixed
issue — add_oracle (added in accensa#262) is missing its body/closing brace and
currently fails to compile at all. Left alone here since it's unrelated
to this change and its intended whitelist-insertion logic isn't specified
anywhere I could find.
@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

@DooseWayo 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

@wagmiiii
wagmiiii merged commit 2a36681 into accensa:main Aug 30, 2026
4 of 9 checks passed
tecmalik added a commit to tecmalik/accensa-contracts that referenced this pull request Aug 30, 2026
Merging main (accensa#273) resurrected a dead local ('names' collected from
VECTORS) in test_shared_vectors_cover_required_edge_cases that the
substring checks never use. It tripped clippy -D warnings (unused
variable) in the lib-test build; removed it.
tecmalik added a commit to tecmalik/accensa-contracts that referenced this pull request Aug 30, 2026
Merging main (accensa#273) re-resolved workspace dependencies (Cargo.lock), which
changes the deployed-contract wasm hash bytes recorded in the soroban test
snapshots. Regenerated by the test harness; all tests pass against them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants