proposal_subdao.gno
3.95 Kb ยท 156 lines
1package commondao
2
3import (
4 "errors"
5 "strings"
6 "time"
7
8 "gno.land/p/moul/addrset"
9 "gno.land/p/moul/md"
10 "gno.land/p/nt/commondao"
11)
12
13// newSubDAOPropDefinition creates a new proposal definition for adding a SubDAO.
14func newSubDAOPropDefinition(parent *commondao.CommonDAO, name string, members *addrset.Set) subDAOPropDefinition {
15 if parent == nil {
16 panic("parent DAO is required")
17 }
18
19 name = strings.TrimSpace(name)
20 assertDAONameIsValid(name)
21
22 return subDAOPropDefinition{
23 parent: parent,
24 name: name,
25 members: members,
26 }
27}
28
29// subDAOPropDefinition defines a proposal type for adding a SubDAO.
30type subDAOPropDefinition struct {
31 parent *commondao.CommonDAO
32 name string
33 members *addrset.Set
34}
35
36func (p subDAOPropDefinition) Title() string { return "New SubDAO: " + p.name }
37func (subDAOPropDefinition) VotingPeriod() time.Duration { return time.Hour * 24 * 7 }
38
39func (p subDAOPropDefinition) Body() string {
40 var b strings.Builder
41
42 b.WriteString(md.Paragraph(
43 md.Bold("Parent DAO:") + "\n" + md.Link(p.parent.Name(), daoURL(p.parent.ID())),
44 ))
45
46 b.WriteString(md.Paragraph(
47 md.Bold("SubDAO Name:") + "\n" + p.name,
48 ))
49
50 if p.members != nil && p.members.Size() > 0 {
51 items := make([]string, 0, p.members.Size())
52 p.members.IterateByOffset(0, p.members.Size(), func(addr address) bool {
53 items = append(items, addr.String())
54 return false
55 })
56
57 b.WriteString(md.Paragraph(
58 md.Bold("Members:") + "\n" + md.BulletList(items),
59 ))
60 }
61
62 return b.String()
63}
64
65func (p subDAOPropDefinition) Validate() (err error) {
66 options := getOptions(p.parent.ID())
67 if !(options.AllowSubDAOProposals && options.AllowChildren) {
68 return errors.New("SubDAO support is not enabled")
69 }
70
71 p.parent.Children().ForEach(func(_ int, v any) bool {
72 subDAO := v.(*commondao.CommonDAO)
73 if subDAO.Name() == p.name {
74 err = errors.New("a SubDAO with the same name already exists")
75 return true
76 }
77 return false
78 })
79 return err
80}
81
82func (subDAOPropDefinition) Tally(r commondao.ReadonlyVotingRecord, members commondao.MemberSet) (bool, error) {
83 if !commondao.IsQuorumReached(commondao.QuorumFull, r, members) {
84 return false, commondao.ErrNoQuorum
85 }
86
87 c, success := commondao.SelectChoiceBySuperMajority(r, members.Size())
88 if success {
89 return c == commondao.ChoiceYes, nil
90 }
91 return false, nil
92}
93
94func (p subDAOPropDefinition) Execute(realm) error {
95 subDAO := createSubDAO(p.parent, p.name, nil)
96
97 if p.members != nil {
98 p.members.IterateByOffset(0, p.members.Size(), func(addr address) bool {
99 subDAO.Members().Add(addr)
100 return false
101 })
102 }
103
104 p.parent.Children().Append(subDAO)
105 return nil
106}
107
108// newDissolvePropDefinition creates a new proposal definition for dissolving a SubDAO.
109func newDissolvePropDefinition(dao *commondao.CommonDAO) dissolvePropDefinition {
110 if dao == nil {
111 panic("SubDAO is required")
112 }
113
114 return dissolvePropDefinition{dao}
115}
116
117// dissolvePropDefinition defines a proposal type for dissolving a SubDAO.
118type dissolvePropDefinition struct {
119 dao *commondao.CommonDAO
120}
121
122func (p dissolvePropDefinition) Title() string { return "Dissolve DAO: " + p.dao.Name() }
123func (dissolvePropDefinition) VotingPeriod() time.Duration { return time.Hour * 24 * 7 }
124
125func (p dissolvePropDefinition) Body() string {
126 var b strings.Builder
127
128 b.WriteString(md.Bold("DAO:") + "\n")
129 b.WriteString(md.Link(p.dao.Name(), daoURL(p.dao.ID())))
130
131 return b.String()
132}
133
134func (p dissolvePropDefinition) Validate() (err error) {
135 if p.dao.IsDeleted() {
136 return errors.New("DAO has been already dissolveed")
137 }
138 return nil
139}
140
141func (dissolvePropDefinition) Tally(r commondao.ReadonlyVotingRecord, members commondao.MemberSet) (bool, error) {
142 if !commondao.IsQuorumReached(commondao.QuorumFull, r, members) {
143 return false, commondao.ErrNoQuorum
144 }
145
146 c, success := commondao.SelectChoiceBySuperMajority(r, members.Size())
147 if success {
148 return c == commondao.ChoiceYes, nil
149 }
150 return false, nil
151}
152
153func (p dissolvePropDefinition) Execute(realm) error {
154 p.dao.SetDeleted(true)
155 return nil
156}