Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

doc.gno

4.80 Kb · 81 lines
 1// v0 - Unaudited: This is an initial version that has not yet been formally audited.
 2// A fully audited version will be published as a subsequent release.
 3// Use in production at your own risk.
 4//
 5// Package commondao provides governance primitives following the Common
 6// DAO Spec (docs/CONSTITUTION.md, Appendix): a CommonDAO is a Council (a
 7// set of addresses with equal voting power), a proposal lifecycle decided
 8// by the constitution's default voting rules, and an optional sub-DAO
 9// tree.
10//
11// Proposal types are registered per DAO: a ProposalKind couples a
12// registry name with a definition factory New(dao ReadonlyCommonDAO,
13// args), and Propose(creator, kind, args) accepts exactly the kinds
14// registered on the DAO. New receives only a readonly view, so it cannot
15// mutate the DAO before the vote; a kind that must mutate state on
16// execution captures its target *CommonDAO from args (populated only by
17// trusted callers) and mutates in its executor. RegisterKind /
18// DeregisterKind / HasKind / KindNames and the WithProposalKind option
19// are the registry primitives; the package ships one concrete kind,
20// ExecutionKind (arbitrary execution), and no governance meta-kinds —
21// managing a DAO's kind set through governance is the consuming realm's
22// job.
23//
24// Proposals snapshot the council as their electorate at creation and
25// are decided the moment the outcome is mathematically settled: with
26// integer math over D = |electorate| - abstains, a supermajority
27// (3*yes >= 2*D) passes, a NO majority (2*no > D) dismisses, and
28// proposals still undecided at their voting deadline are dismissed.
29//
30// A DAO may carry a treasury address and frozen flag; the package only
31// stores them - hosting realms derive the address and move the funds.
32//
33// A *CommonDAO is a mutable handle for the realm that owns it: never
34// accept one from, or return one to, an untrusted realm - readonly views
35// (CommonDAO.Readonly) are the only safe handles to cross a realm
36// boundary. See the package README for details.
37//
38// # Extending commondao in your own realm
39//
40// This package is mostly mechanism: it ships the ExecutionKind concrete kind
41// (with a default voting policy) and the registry primitives, and leaves the
42// rest of governance policy — which kinds a DAO accepts, how it manages them,
43// and any per-kind constraints such as a treasury freeze — to the consuming
44// realm. To add a proposal type of your own:
45//
46//   - Author a ProposalKind: a type with Name() string and
47//     New(dao ReadonlyCommonDAO, args any) (ProposalDefinition, error). Make
48//     the definition Executable (Executor() returns an ExecFunc) if it
49//     mutates state on approval. If its executor moves funds from a DAO other
50//     than the proposal's host, have the HOST realm consume a Funded-style
51//     contract (FundingDAOID() uint64) — minting a DAO sub needs the host's
52//     cur, so this contract is host-consumed, not package-dispatched; define
53//     it in your realm, as the reference realm does.
54//   - Apply your own policy. ExecutionKind runs the closure as-is (no check
55//     beyond a non-nil Fn), so if your realm has treasury constraints (e.g. a
56//     freeze flag) do NOT catalog ExecutionKind directly: author your own
57//     execution kind whose definition wraps the closure with a Validable
58//     check (Validate() error) enforcing those constraints, so arbitrary
59//     execution cannot bypass them. The reference realm does this so a frozen
60//     DAO cannot drain its own treasury through an execution proposal.
61//   - Seed it. The owning realm holds the DAO handle, so no proposal is
62//     needed: pass commondao.New(WithProposalKind(YourKind{}), …) at
63//     construction, or call dao.RegisterKind(YourKind{}) directly.
64//   - Author a typed, CLI-friendly wrapper
65//     CreateYourProposal(cur realm, daoID uint64, …params…): council-gate the
66//     caller, build the args struct, and call Propose. This is the only
67//     public entry, so the args-capture trust boundary holds.
68//   - Optionally add a runtime governance toggle. If the council should
69//     register/deregister kinds by vote (rather than only at construction),
70//     author a manage-kinds-style ProposalKind whose executor calls
71//     RegisterKind/DeregisterKind, and keep that managing kind itself
72//     un-deregisterable so the DAO can always recover.
73//
74// Trust boundary: New receives only a ReadonlyCommonDAO, so a kind — even an
75// externally authored one — cannot mutate the host at Propose time. The
76// mutable *CommonDAO reaches a definition only through args, which your
77// trusted wrapper populates (an external proposer cannot obtain one). On
78// execution the host passes the DAO's terminal, RealmSend-only sub, so a
79// fund-moving executor is bounded to that one DAO address. See the reference
80// realm gno.land/r/nt/commondao/v0 for a full worked example.
81package commondao