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}