govern.gno
4.34 Kb · 114 lines
1package bubble
2
3import (
4 governor "gno.land/p/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/governor/v0"
5)
6
7// The governor: kourt's engine on this ledger, with this realm's own powers installed under the reserved prefix.
8// Everything about proposals — kinds, tally, rules, sweep, pages — is the engine's; what is here is what only a
9// realm can do: hold a live cur, check it, read who is calling, dispatch a decided kind with a sub-realm.
10//
11// "Usable for governance flexibly as we build it out": a new power is a Kind any realm can Offer (published,
12// immutable code plus the bar it would pass at) and the holders adopt by govern:adopt. The token is never
13// redeployed to gain a power.
14
15type (
16 Kind = governor.Kind
17 Rules = governor.Rules
18)
19
20func NewRules(quorumBps, thresholdBps, votingBlocks, delayBlocks, graceBlocks, proposeBps int64) Rules {
21 return governor.NewRules(quorumBps, thresholdBps, votingBlocks, delayBlocks, graceBlocks, proposeBps)
22}
23
24func TextOnly(s string) error { return governor.TextOnly(s) }
25
26// engine is this realm's governor. Unexported: whoever holds it can adopt a kind without a vote.
27var engine = governor.New(ledger, ledger)
28
29func init() {
30 installKinds()
31}
32
33// dispatch runs a decided kind with a SUB-realm, never this realm's own capability (the engine's note on
34// dispatch: a kind holding the live cur could cross into anything that trusts this realm).
35func dispatch(cur realm) governor.Dispatch {
36 return func(k Kind, subpath, payload string) error {
37 return k.Do(0, cur.Sub(subpath), payload)
38 }
39}
40
41// Offer publishes a kind. It grants nothing: the holders adopt it by vote.
42func Offer(cur realm, k Kind, r Rules) { engine.Offer(caller(cur), k, r) }
43
44// Propose asks a question under an adopted kind. A money kind carries its absolute turnout floor (kinds.gno).
45func Propose(cur realm, kind, payload, title string) int64 {
46 who := caller(cur)
47 var id int64
48 if floor := quorumFloor(kind); floor > 0 {
49 id = engine.ProposeWithQuorum(who, kind, payload, title, floor)
50 } else {
51 id = engine.Propose(who, kind, payload, title)
52 }
53 if len(askedKinds) > 512 { // a guard, not a record: only decided-but-unnoted money votes need it, and those are few
54 askedKinds = map[int64]string{}
55 }
56 askedKinds[id] = kind
57 return id
58}
59
60// Vote casts the caller's weight as of the proposal's sealed epoch: "yes", "no" or "abstain".
61func Vote(cur realm, id int64, choice string) { engine.Vote(caller(cur), id, choice) }
62
63func VoteWithReason(cur realm, id int64, choice, reason string) {
64 engine.VoteWithReason(caller(cur), id, choice, reason)
65}
66
67// Cancel withdraws the proposer's own open proposal.
68func Cancel(cur realm, id int64) { engine.Cancel(caller(cur), id) }
69
70// Settle writes down a conclusion the rules already reached. Permissionless. A decided money vote's turnout goes
71// into the bar's memory (kinds.gno).
72func Settle(cur realm, id int64) {
73 engine.Settle(caller(cur), id)
74 if isMoneyKind(kindOf(id)) {
75 noteTurnout(id)
76 }
77}
78
79// Execute runs a decided proposal after its delay. Permissionless.
80func Execute(cur realm, id int64) {
81 engine.Execute(caller(cur), id, dispatch(cur))
82 if isMoneyKind(kindOf(id)) {
83 noteTurnout(id)
84 }
85}
86
87// kindOf is the kind a proposal was asked under, as this realm noted it at Propose (the engine describes a
88// proposal by its payload alone); an id it never saw is "".
89func kindOf(id int64) string { return askedKinds[id] }
90
91// askedKinds is id -> kind for the proposals asked here, the last few hundred.
92var askedKinds = map[int64]string{}
93
94func ReleaseRoll(cur realm, id int64) { engine.ReleaseRoll(caller(cur), id) }
95
96func Sweep(cur realm) {
97 caller(cur)
98 engine.Sweep()
99}
100
101// ------------------------------------------------------------------ reads --
102
103func State(id int64) string { return engine.State(id) }
104func Describe(id int64) string { return engine.Describe(id) }
105func Preview(kind, payload string) string { return engine.Preview(kind, payload) }
106func HasVoted(id int64, who address) bool { return engine.HasVoted(id, who) }
107func Tally(id int64) (yes, no, abstain, total int64) { return engine.Tally(id) }
108func KindRules(name string) (Rules, bool) { return engine.KindRules(name) }
109
110func Timings(id int64) (opened, closes, ready, expires int64) { return engine.Timings(id) }
111
112func VoteOf(id int64, who address) (choice string, weight int64, ok bool) {
113 return engine.VoteOf(id, who)
114}