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

v0 source pure

v0 - Unaudited: This is an initial version that has not yet been formally audited. A fully audited version will be pu...

Readme View source

v0 - Unaudited This is an initial version of this package that has not yet been formally audited. A fully audited version will be published as a subsequent release. Use in production at your own risk.

CommonDAO Package

CommonDAO is a general-purpose package that provides support to implement custom Decentralized Autonomous Organizations (DAO) on Gno.land.

It offers a minimal and flexible framework for building DAOs, with customizable options that adapt across multiple use cases.

Core Types

Package contains some core types which are important in any DAO implementation, these are CommonDAO, ProposalDefinition, Proposal and Vote.

1. CommonDAO Type

CommonDAO type is the main type used to define DAOs, allowing standalone DAO creation or hierarchical tree based ones.

During creation, it accepts many optional arguments some of which are handy depending on the DAO type. For example, standalone DAOs might use IDs, a name and description to uniquely identify individual DAOs; Hierarchical ones might choose to use slugs instead of IDs, or even a mix of both.

DAO Creation Examples

Standalone DAO:

1import "gno.land/p/nt/commondao/v0"
2
3dao := commondao.New(
4    commondao.WithID(1),
5    commondao.WithName("MyDAO"),
6    commondao.WithDescription("An example DAO"),
7    commondao.WithMember("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
8    commondao.WithMember("g1hy6zry03hg5d8le9s2w4fxme6236hkgd928dun"),
9)

Hierarchical DAO:

 1import "gno.land/p/nt/commondao/v0"
 2
 3dao := commondao.New(
 4    commondao.WithSlug("parent"),
 5    commondao.WithName("ParentDAO"),
 6    commondao.WithMember("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"),
 7)
 8
 9subDAO := commondao.New(
10    commondao.WithSlug("child"),
11    commondao.WithName("ChildDAO"),
12    commondao.WithParent(dao),
13)

2. ProposalDefinition Type

Proposal definitions are the way proposal types are implemented in commondao. Definitions are required when creating a new proposal because they define the behavior of the proposal.

Generally speaking, proposals can be divided in two types, one are the general (a.k.a. text proposals), and the other are the executable ones. The difference is that executable ones modify the blockchain state when they are executed after they have been approved, while general ones don't, they are usually used to signal or measure sentiment, for example regarding a relevant issue.

Creating a new proposal type requires implementing the following interface:

 1type ProposalDefinition interface {
 2    // Title returns proposal title.
 3    Title() string
 4
 5    // Body returns proposal's body.
 6    // It usually contains description or values that are specific to
 7    // the proposal, like a description of the proposal's motivation
 8    // or the list of values that would be applied when the proposal
 9    // is approved.
10    Body() string
11
12    // VotingPeriod returns the period where votes are allowed after
13    // proposal creation. It's used to calculate the voting deadline
14    // from the proposal's creationd date.
15    VotingPeriod() time.Duration
16
17    // Tally counts the number of votes and verifies if proposal passes.
18    // It receives a voting context containing a readonly record with the votes
19    // that has been submitted for the proposal and also the list of DAO members.
20    Tally(VotingContext) (passes bool, _ error)
21}

This minimal interface is the one required for general proposal types. Here the most important method is the Tally() one. It's used to check whether a proposal passes or not.

Within Tally() votes can be counted using different rules depending on the proposal type, some proposal types might decide if there is consensus by using super majority while others might decide using plurality for example, or even just counting that a minimum number of certain positive votes have been submitted to approve a proposal.

CommonDAO provides a couple of helpers for this, to cover some cases:

  • SelectChoiceByAbsoluteMajority()
  • SelectChoiceBySuperMajority() (using a 2/3s threshold)
  • SelectChoiceByPlurality()

2.1. Executable Proposals

Proposal definitions have optional features that could be implemented to extend the proposal type behaviour. One of those is required to enable execution support.

A proposal can be executable implementing the Executable interface as part of the new proposal definition:

1type Executable interface {
2    // Executor returns a function to execute the proposal.
3    Executor() func(realm) error
4}

The crossing function returned by the Executor() method is where the realm changes are made once the proposal is executed.

Other features can be enabled by implementing the Validable interface and the CustomizableVoteChoices one, as a way to separate pre-execution validation and to support proposal voting choices different than the default ones (YES, NO and ABSTAIN).

3. Proposal Type

Proposals are key for governance, they are the main mechanic that allows DAO members to engage on governance.

They are usually not created directly but though CommonDAO instances, by calling the CommonDAO.Propose() or CommonDAO.MustPropose() methods. Though, alternatively, proposals could be added to CommonDAO's active proposals storage using CommonDAO.ActiveProposals().Add().

1import (
2    "gno.land/p/nt/commondao/v0"
3    "gno.land/r/example/mydao"
4)
5
6dao := commondao.New()
7creator := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
8propDef := mydao.NewGeneralProposalDefinition("Title", "Description")
9proposal := dao.MustPropose(creator, propDef)

3.1. Voting on Proposals

The preferred way to submit a vote, once a proposal is created, is by calling the CommonDAO.Vote() method because it performs sanity checks before a vote is considered valid; Alternatively votes can be directly added without sanity checks to the proposal's voting record by calling Proposal.VotingRecord().AddVote().

3.2. Voting Record

Each proposal keeps track of their submitted votes within an internal voting record. CommonDAO package defines it as a VotingRecord type.

The voting record of a proposal can be getted by calling its Proposal.VotingRecord() method.

Right now proposals have a single voting record but the plan is to support multiple voting records per proposal as an optional feature, which could be used in cases where a proposal must track votes in multiple independent records, for example in cases where a proposal could be promoted to a different DAO with a different set of members.

4. Vote Type

Vote type defines the structure to store information for individual proposal votes. Apart from the normally mandatory Address and voting Choice fields, there are two optional fields that can be useful in different use cases; These fields are Reason which can store a string with the reason for the vote, and Context which can be used to store generic values related to the vote, for example vote weight information.

It's very important to be careful when using the Context field, in case references/pointers are assigned to it because they could potentially be accessed anywhere, which could lead to unwanted indirect modifications.

Vote type is defined as:

 1type Vote struct {
 2    // Address is the address of the user that this vote belons to.
 3    Address address
 4
 5    // Choice contains the voted choice.
 6    Choice VoteChoice
 7
 8    // Reason contains an optional reason for the vote.
 9    Reason string
10
11    // Context can store any custom voting values related to the vote.
12    Context any
13}

Secondary Types

There are other types which can be handy for some implementations which might require to store DAO members or proposals in a custom location, or that might need member grouping support.

1. MemberStorage and ProposalStorage Types

These two types allows storing and iterating DAO members and proposals. They support DAO implementations that might require storing either members or proposals in an external realm other than the DAO realm.

CommonDAO package provides implementations that use AVL trees under the hood for storage and lookup.

Custom implementations are supported though the MemberStorage and ProposalStorage interfaces:

 1type MemberStorage interface {
 2	// Size returns the number of members in the storage.
 3	Size() int
 4
 5	// Has checks if a member exists in the storage.
 6	Has(address) bool
 7
 8	// Add adds a member to the storage.
 9	Add(address) bool
10
11	// Remove removes a member from the storage.
12	Remove(address) bool
13
14	// Grouping returns member groups when supported.
15	Grouping() MemberGrouping
16
17	// IterateByOffset iterates members starting at the given offset.
18	IterateByOffset(offset, count int, fn func(address) bool)
19}
20
21type ProposalStorage interface {
22	// Has checks if a proposal exists.
23	Has(id uint64) bool
24
25	// Get returns a proposal or nil when proposal doesn't exist.
26	Get(id uint64) *Proposal
27
28	// Add adds a proposal to the storage.
29	Add(*Proposal)
30
31	// Remove removes a proposal from the storage.
32	Remove(id uint64)
33
34	// Size returns the number of proposals that the storage contains.
35	Size() int
36
37	// Iterate iterates proposals.
38	Iterate(offset, count int, reverse bool, fn func(*Proposal) bool) bool
39}

2. MemberGrouping and MemberGroup Types

Members grouping is an optional feature that provides support for DAO members grouping.

Grouping can be useful for DAOs that require grouping users by roles or tiers for example.

The MemberGrouping type is a collection of member groups, while the MemberGroup is a group of members with metadata.

Grouping by Role Example

 1import "gno.land/p/nt/commondao/v0"
 2
 3storage := commondao.NewMemberStorageWithGrouping()
 4
 5// Add a member that doesn't belong to any group
 6storage.Add("g1...a")
 7
 8// Create a member group for owners
 9owners, err := storage.Grouping().Add("owners")
10if err != nil {
11  panic(err)
12}
13
14// Add a member to the owners group
15owners.Members().Add("g1...b")
16
17// Add voting power to owners group metadata
18owners.SetMeta(3)
19
20// Create a member group for moderators
21moderators, err := storage.Grouping().Add("moderators")
22if err != nil {
23  panic(err)
24}
25
26// Add voting power to moderators group metadata
27moderators.SetMeta(1)
28
29// Add members to the moderators group
30moderators.Members().Add("g1...c")
31moderators.Members().Add("g1...d")

Overview

v0 - Unaudited: This is an initial version that has not yet been formally audited. A fully audited version will be published as a subsequent release. Use in production at your own risk.

Package provides support to implement custom Decentralized Autonomous Organizations (DAO). It aims to be minimal and flexible, allowing the implementation of multiple DAO use cases, like standalone or hierarchical tree based DAOs.

Constants 5

const MaxCustomVoteChoices

1const MaxCustomVoteChoices = 10
source

MaxCustomVoteChoices defines the maximum number of custom vote choices that a proposal definition can define.

const PathSeparator

1const PathSeparator = "/"
source

PathSeparator is the separator character used in DAO paths.

Variables 3

var ErrExecutionNotAllowed, ErrInvalidVoteChoice, ErrNotMember, ErrOverflow, ErrProposalNotFound, ErrVotingDeadlineNotMet, ErrVotingDeadlinePassed, ErrWithdrawalNotAllowed

 1var (
 2	ErrExecutionNotAllowed  = errors.New("proposal must pass before execution")
 3	ErrInvalidVoteChoice    = errors.New("invalid vote choice")
 4	ErrNotMember            = errors.New("account is not a member of the DAO")
 5	ErrOverflow             = errors.New("next ID overflows uint64")
 6	ErrProposalNotFound     = errors.New("proposal not found")
 7	ErrVotingDeadlineNotMet = errors.New("voting deadline not met")
 8	ErrVotingDeadlinePassed = errors.New("voting deadline has passed")
 9	ErrWithdrawalNotAllowed = errors.New("withdrawal not allowed for proposals with votes")
10)
source

var ErrVoteExists

1var ErrVoteExists = errors.New("user already voted")
source

ErrVoteExists indicates that a user already voted.

Functions 38

func CountStorageMembers

1func CountStorageMembers(s *ReadonlyMemberStorage) int
source

CountStorageMembers returns the total number of members in the storage. It counts all members in each group and the ones without group.

func IsQuorumReached

1func IsQuorumReached(quorum float64, r ReadonlyVotingRecord, members ReadonlyMemberStorage) bool
source

IsQuorumReached checks if a participation quorum is reach.

func MustExecute

1func MustExecute(e Executable, rlm realm)
source

MustExecute executes an executable proposal or panics on error.

rlm is the realm authority threaded into the executor via cross(rlm). MustExecute itself is not a crossing function (rlm sits in a non-first parameter slot) because /p/ production code cannot declare crossing functions — callers pass `cur` directly as the rlm argument.

func MustValidate

1func MustValidate(v Validable)
source

MustValidate validates that a proposal is valid for the current state or panics on error.

func New

1func New(options ...Option) *CommonDAO
source

New creates a new common DAO.

func MustNewMemberGroup

1func MustNewMemberGroup(name string, members MemberStorage) MemberGroup
source

MustNewMemberGroup creates a new group of members or panics on error.

func NewMemberGroup

1func NewMemberGroup(name string, members MemberStorage) (MemberGroup, error)
source

NewMemberGroup creates a new group of members.

func NewMemberGrouping

1func NewMemberGrouping(options ...MemberGroupingOption) MemberGrouping
source

NewMemberGrouping creates a new members grouping.

func UseStorageFactory

1func UseStorageFactory(fn func(group string) MemberStorage) MemberGroupingOption
source

SECURITY XXX: UseStorageFactory captures a caller-supplied factory that returns the MemberStorage used to track who is a DAO member. A malicious factory can return a MemberStorage impl that lies about membership — always-true (everyone is a member, votes pass trivially) or always-false (legitimate members are locked out). This isn't a cur-leak; it's a behavior-substitution risk on the data layer the DAO's voting and proposal logic depends on. Fix: document that the factory must come from trusted code (a hardcoded constructor in the DAO realm itself), and never accept a UseStorageFactory option from external-realm input. Or restrict to a canonical-impl allowlist (type-switch on known MemberStorage types) in commondao itself.

UseStorageFactory assigns a custom member storage creation function to the grouping. Creation function is called each time a member group is added, with the name of the group as the only argument, to create a storage where the new group stores its members.

func WithGroups

1func WithGroups(names ...string) MemberGroupingOption
source

WithGroups creates multiple members groups. To use a custom member storage factory to create the groups make sure that this option comes after the `UseStorageFactory()` option, otherwise groups are created using the default factory which is `commondao.NewMemberStorage()`.

func NewMemberStorage

1func NewMemberStorage() MemberStorage
source

NewMemberStorage creates a new member storage. Function returns a new member storage that doesn't support member groups. This type of storage is useful when there is no need to group members.

func NewMemberStorageWithGrouping

1func NewMemberStorageWithGrouping(options ...MemberGroupingOption) MemberStorage
source

NewMemberStorageWithGrouping a new member storage with support for member groups. Member groups can be used by implementations that require grouping users by roles or by tiers for example.

func DisableVotingDeadlineCheck

1func DisableVotingDeadlineCheck() Option
source

DisableVotingDeadlineCheck disables voting deadline check when voting or executing proposals. By default CommonDAO checks that the proposal voting deadline has not been met when a new vote is submitted, before registering the vote, and on proposal execution it also checks that voting deadline has been met before executing a proposal.

Disabling these checks can be useful in different use cases, moving the responsibility to check the deadline to the commondao package caller. One example where this could be useful would be in case where 100% or a required number of members of a DAO vote on a proposal and reach consensus before the deadline is met, otherwise proposal would have to wait until deadline to be executed.

func WithActiveProposalStorage

1func WithActiveProposalStorage(s ProposalStorage) Option
source

WithActiveProposalStorage assigns a custom storage for active proposals. A default empty proposal storage is used when the custopm storage is nil. Custom storage implementations can be used to store proposals in a different location.

func WithChildren

1func WithChildren(children ...*CommonDAO) Option
source

WithChildren assigns one or more direct child SubDAOs to the DAO.

func WithDescription

1func WithDescription(description string) Option
source

WithDescription assigns a description to the DAO.

func WithFinishedProposalStorage

1func WithFinishedProposalStorage(s ProposalStorage) Option
source

WithFinishedProposalStorage assigns a custom storage for finished proposals. A default empty proposal storage is used when the custopm storage is nil. Custom storage implementations can be used to store proposals in a different location.

func WithID

1func WithID(id uint64) Option
source

WithID assigns a unique identifier to the DAO.

func WithMember

1func WithMember(addr address) Option
source

WithMember assigns a member to the DAO.

func WithMemberStorage

1func WithMemberStorage(s MemberStorage) Option
source

WithMemberStorage assigns a custom member storage to the DAO. An empty member storage is used by default if the specified storage is nil.

func WithName

1func WithName(name string) Option
source

WithName assigns a name to the DAO.

func WithParent

1func WithParent(p *CommonDAO) Option
source

WithParent assigns a parent DAO.

func WithSlug

1func WithSlug(slug string) Option
source

WithSlug assigns a URL slug to the DAO.

func NewProposal

1func NewProposal(id uint64, creator address, d ProposalDefinition) (*Proposal, error)
source

NewProposal creates a new DAO proposal.

func NewProposalStorage

1func NewProposalStorage() ProposalStorage
source

NewProposalStorage creates a new proposal storage.

func MustNewReadonlyMemberGroup

1func MustNewReadonlyMemberGroup(g MemberGroup) *ReadonlyMemberGroup
source

MustNewReadonlyMemberGroup creates a new readonly member group or panics on error.

func NewReadonlyMemberGroup

1func NewReadonlyMemberGroup(g MemberGroup) (*ReadonlyMemberGroup, error)
source

NewReadonlyMemberGroup creates a new readonly member group.

func MustNewReadonlyMemberGrouping

1func MustNewReadonlyMemberGrouping(g MemberGrouping) *ReadonlyMemberGrouping
source

MustNewReadonlyMemberGrouping creates a new grouping if member or panics on error.

func NewReadonlyMemberGrouping

1func NewReadonlyMemberGrouping(g MemberGrouping) (*ReadonlyMemberGrouping, error)
source

NewReadonlyMemberGrouping creates a new grouping if member.

func MustNewReadonlyMemberStorage

1func MustNewReadonlyMemberStorage(s MemberStorage) *ReadonlyMemberStorage
source

MustNewReadonlyMemberStorage creates a new readonly member storage or panics on error.

func NewReadonlyMemberStorage

1func NewReadonlyMemberStorage(s MemberStorage) (*ReadonlyMemberStorage, error)
source

NewReadonlyMemberStorage creates a new readonly member storage.

func FindMostVotedChoice

1func FindMostVotedChoice(r ReadonlyVotingRecord) VoteChoice
source

FindMostVotedChoice returns the most voted choice. ChoiceNone is returned when there is a tie between different voting choices or when the voting record has are no votes.

func SelectChoiceByAbsoluteMajority

1func SelectChoiceByAbsoluteMajority(r ReadonlyVotingRecord, membersCount int) (VoteChoice, bool)
source

SelectChoiceByAbsoluteMajority select the vote choice by absolute majority. Vote choice is a majority when chosen by more than half of the votes. Absolute majority considers abstentions when counting votes.

func SelectChoiceByPlurality

1func SelectChoiceByPlurality(r ReadonlyVotingRecord) (VoteChoice, bool)
source

SelectChoiceByPlurality selects the vote choice by plurality. The choice will be considered a majority if it has votes and if there is no other choice with the same number of votes. A tie won't be considered majority.

func SelectChoiceBySuperMajority

1func SelectChoiceBySuperMajority(r ReadonlyVotingRecord, membersCount int) (VoteChoice, bool)
source

SelectChoiceBySuperMajority select the vote choice by super majority using a 2/3s threshold. Abstentions are considered when calculating the super majority choice.

func MustNewVotingContext

1func MustNewVotingContext(r *VotingRecord, s MemberStorage) VotingContext
source

MustNewVotingContext creates a new voting context or panics on error.

func NewVotingContext

1func NewVotingContext(r *VotingRecord, s MemberStorage) (VotingContext, error)
source

NewVotingContext creates a new voting context.

func CollectVotes

1func CollectVotes(ctx VotingContext, groups ...string) (*VotingRecord, error)
source

CollectVotes returns an voting record containing votes of members from one or more groups. Returned tree uses member account address as key and `commondao.Vote` as value.

Types 26

type CommonDAO

struct
 1type CommonDAO struct {
 2	id                         uint64
 3	slug                       string
 4	name                       string
 5	description                string
 6	parent                     *CommonDAO
 7	children                   list.IList
 8	members                    MemberStorage
 9	genID                      seqid.ID
10	activeProposals            ProposalStorage
11	finishedProposals          ProposalStorage
12	deleted                    bool // Soft delete
13	disableVotingDeadlineCheck bool
14}
source

CommonDAO defines a DAO.

Methods on CommonDAO

func ActiveProposals

method on CommonDAO
1func (dao CommonDAO) ActiveProposals() ProposalStorage
source

ActiveProposals returns active DAO proposals.

func Children

method on CommonDAO
1func (dao CommonDAO) Children() list.IList
source

Children returns a list with the direct DAO children. Each item in the list is a reference to a CommonDAO instance.

func Description

method on CommonDAO
1func (dao CommonDAO) Description() string
source

Description returns DAO's description.

func Execute

method on CommonDAO
1func (dao *CommonDAO) Execute(proposalID uint64, rlm realm) error
source

Execute executes a proposal.

By default active proposals can only be executed after their voting deadline passes. DAO deadline checks can optionally be disabled using the `DisableVotingDeadlineCheck` option.

rlm is the realm authority threaded into the executor via cross(rlm). Execute itself is not a crossing function (rlm sits in a non-first parameter slot) because /p/ production code cannot declare crossing functions — callers pass `cur` directly as the rlm argument.

func FinishedProposals

method on CommonDAO
1func (dao CommonDAO) FinishedProposals() ProposalStorage
source

FinishedProposalsi returns finished DAO proposals.

func GetProposal

method on CommonDAO
1func (dao CommonDAO) GetProposal(proposalID uint64) *Proposal
source

GetProposal returns a proposal or nil when proposal is not found.

func ID

method on CommonDAO
1func (dao CommonDAO) ID() uint64
source

ID returns DAO's unique identifier.

func IsDeleted

method on CommonDAO
1func (dao CommonDAO) IsDeleted() bool
source

IsDeleted returns true when DAO has been soft deleted.

func Members

method on CommonDAO
1func (dao CommonDAO) Members() MemberStorage
source

Members returns the list of DAO members.

func MustPropose

method on CommonDAO
1func (dao *CommonDAO) MustPropose(creator address, d ProposalDefinition) *Proposal
source

MustPropose creates a new DAO proposal or panics on error.

func Name

method on CommonDAO
1func (dao CommonDAO) Name() string
source

Name returns DAO's name.

func Parent

method on CommonDAO
1func (dao CommonDAO) Parent() *CommonDAO
source

Parent returns the parent DAO. Null can be returned when DAO has no parent assigned.

func Path

method on CommonDAO
1func (dao CommonDAO) Path() string
source

Path returns the full path to the DAO. Paths are normally used when working with hierarchical DAOs and is created by concatenating DAO slugs.

func Propose

method on CommonDAO
1func (dao *CommonDAO) Propose(creator address, d ProposalDefinition) (*Proposal, error)
source

Propose creates a new DAO proposal.

func SetDeleted

method on CommonDAO
1func (dao *CommonDAO) SetDeleted(deleted bool)
source

SetDeleted changes DAO's soft delete flag.

func Slug

method on CommonDAO
1func (dao CommonDAO) Slug() string
source

Slug returns DAO's URL slug.

func TopParent

method on CommonDAO
1func (dao *CommonDAO) TopParent() *CommonDAO
source

TopParent returns the topmost parent DAO. The top parent is the root of the DAO tree.

func Vote

method on CommonDAO
1func (dao *CommonDAO) Vote(member address, proposalID uint64, c VoteChoice, reason string) error
source

Vote submits a new vote for a proposal.

By default votes are only allowed to members of the DAO when the proposal is active, and within the voting period. No votes are allowed once the voting deadline passes. DAO deadline checks can optionally be disabled using the `DisableVotingDeadlineCheck` option.

func Withdraw

method on CommonDAO
1func (dao *CommonDAO) Withdraw(proposalID uint64) error
source

Withdraw withdraws a proposal that has no votes. Only proposals without votes can be withdrawn, and once withdrawn they are considered finished.

type CustomizableVoteChoices

interface
1type CustomizableVoteChoices interface {
2	// CustomVoteChoices returns a list of valid voting choices.
3	// Choices are considered valid only when there are at least two possible choices
4	// otherwise proposal defaults to using YES, NO and ABSTAIN as valid choices.
5	CustomVoteChoices() []VoteChoice
6}
source

CustomizableVoteChoices defines an interface for proposal definitions that want to customize the list of allowed voting choices.

type ExecFunc

func
1type ExecFunc func(realm) error
source

ExecFunc defines a type for functions that executes proposals.

type Executable

interface
1type Executable interface {
2	// Executor returns a function to execute the proposal.
3	Executor() ExecFunc
4}
source

Executable defines an interface for proposal definitions that modify state on approval. Once proposals are executed they are archived and considered finished.

type MemberGroup

interface
 1type MemberGroup interface {
 2	// Name returns the name of the group.
 3	Name() string
 4
 5	// Members returns the members that belong to the group.
 6	Members() MemberStorage
 7
 8	// SetMeta sets any metadata relevant to the group.
 9	// Metadata can be used to store data which is specific to the group.
10	// Usually can be used to store parameter values which would be useful
11	// during proposal voting or tallying to resolve things like voting
12	// weights or rights for example.
13	SetMeta(any)
14
15	// GetMeta returns the group metadata.
16	GetMeta() any
17}
source

MemberGroup defines an interface for a group of members.

type MemberGroupIterFn

func
1type MemberGroupIterFn func(MemberGroup) bool
source

MemberGroupIterFn defines a callback to iterate DAO members groups.

type MemberGrouping

interface
 1type MemberGrouping interface {
 2	// Size returns the number of groups that grouping contains.
 3	Size() int
 4
 5	// Has checks if a group exists.
 6	Has(name string) bool
 7
 8	// Add adds an new member group if it doesn't exists.
 9	Add(name string) (MemberGroup, error)
10
11	// Get returns a member group.
12	Get(name string) (_ MemberGroup, found bool)
13
14	// Delete deletes a member group.
15	Delete(name string) error
16
17	// IterateByOffset iterates all member groups.
18	// The callback can return true to stop iteration.
19	IterateByOffset(offset, count int, fn MemberGroupIterFn) (stopped bool)
20}
source

MemberGrouping defines an interface for storing multiple member groups. Member grouping can be used by implementations that require grouping users by roles or by tiers for example.

type MemberGroupingOption

func
1type MemberGroupingOption func(MemberGrouping)
source

MemberGroupingOption configures member groupings.

type MemberIterFn

func
1type MemberIterFn func(address) bool
source

MemberIterFn defines a callback to iterate DAO members.

type MemberStorage

interface
 1type MemberStorage interface {
 2	// Size returns the number of members in the storage.
 3	Size() int
 4
 5	// Has checks if a member exists in the storage.
 6	Has(address) bool
 7
 8	// Add adds a member to the storage.
 9	// Returns true if the member is added, or false if it already existed.
10	Add(address) bool
11
12	// Remove removes a member from the storage.
13	// Returns true if member was removed, or false if it was not found.
14	Remove(address) bool
15
16	// Grouping returns member groups when supported.
17	// When nil is returned it means that grouping of members is not supported.
18	// Member groups can be used by implementations that require grouping users
19	// by roles or by tiers for example.
20	Grouping() MemberGrouping
21
22	// IterateByOffset iterates members starting at the given offset.
23	// The callback can return true to stop iteration.
24	IterateByOffset(offset, count int, fn MemberIterFn) (stopped bool)
25}
source

MemberStorage defines an interface for member storages.

type Option

func
1type Option func(*CommonDAO)
source

Option configures the CommonDAO.

type Proposal

struct
 1type Proposal struct {
 2	id             uint64
 3	status         ProposalStatus
 4	definition     ProposalDefinition
 5	creator        address
 6	record         *VotingRecord // TODO: Add support for multiple voting records
 7	statusReason   string
 8	voteChoices    *bptree.BPTree // string(VoteChoice) -> struct{}
 9	votingDeadline time.Time
10	createdAt      time.Time
11}
source

Proposal defines a DAO proposal.

Methods on Proposal

func CreatedAt

method on Proposal
1func (p Proposal) CreatedAt() time.Time
source

CreatedAt returns the time that proposal was created.

func Creator

method on Proposal
1func (p Proposal) Creator() address
source

Creator returns the address of the account that created the proposal.

func Definition

method on Proposal
1func (p Proposal) Definition() ProposalDefinition
source

Definition returns the proposal definition. Proposal definitions define proposal content and behavior.

func HasVotingDeadlinePassed

method on Proposal
1func (p Proposal) HasVotingDeadlinePassed() bool
source

HasVotingDeadlinePassed checks if the voting deadline has been met.

func ID

method on Proposal
1func (p Proposal) ID() uint64
source

ID returns the unique proposal identifies.

func IsVoteChoiceValid

method on Proposal
1func (p Proposal) IsVoteChoiceValid(c VoteChoice) bool
source

IsVoteChoiceValid checks if a vote choice is valid for the proposal.

func Status

method on Proposal
1func (p Proposal) Status() ProposalStatus
source

Status returns the current proposal status.

func StatusReason

method on Proposal
1func (p Proposal) StatusReason() string
source

StatusReason returns an optional reason that lead to the current proposal status. Reason is mostyl useful when a proposal fails.

func Tally

method on Proposal
1func (p *Proposal) Tally(members MemberStorage) error
source

Tally counts votes and updates proposal status with the current outcome. Proposal status is updated to "passed" when proposal is approved or to "rejected" if proposal doesn't pass.

func Validate

method on Proposal
1func (p Proposal) Validate() error
source

Validate validates that a proposal is valid for the current state. Validation is done when proposal status is active and when the definition supports validation.

func VoteChoices

method on Proposal
1func (p Proposal) VoteChoices() []VoteChoice
source

VoteChoices returns the list of vote choices allowed for the proposal.

func VotingDeadline

method on Proposal
1func (p Proposal) VotingDeadline() time.Time
source

VotingDeadline returns the deadline after which no more votes should be allowed.

func VotingRecord

method on Proposal
1func (p Proposal) VotingRecord() *VotingRecord
source

VotingRecord returns a record that contains all the votes submitted for the proposal.

type ProposalDefinition

interface
 1type ProposalDefinition interface {
 2	// Title returns the proposal title.
 3	Title() string
 4
 5	// Body returns proposal's body.
 6	// It usually contains description or values that are specific to the proposal,
 7	// like a description of the proposal's motivation or the list of values that
 8	// would be applied when the proposal is approved.
 9	Body() string
10
11	// VotingPeriod returns the period where votes are allowed after proposal creation.
12	// It is used to calculate the voting deadline from the proposal's creationd date.
13	VotingPeriod() time.Duration
14
15	// Tally counts the number of votes and verifies if proposal passes.
16	// It receives a voting context containing a readonly record with the votes
17	// that has been submitted for the proposal and also the list of DAO members.
18	Tally(VotingContext) (passes bool, _ error)
19}
source

ProposalDefinition defines an interface for custom proposal definitions. These definitions define proposal content and behavior, they esentially allow the definition for different proposal types.

type ProposalStatus

ident
1type ProposalStatus string
source

ProposalStatus defines a type for different proposal states.

type ProposalStorage

interface
 1type ProposalStorage interface {
 2	// Has checks if a proposal exists.
 3	Has(id uint64) bool
 4
 5	// Get returns a proposal or nil when proposal doesn't exist.
 6	Get(id uint64) *Proposal
 7
 8	// Add adds a proposal to the storage.
 9	Add(*Proposal)
10
11	// Remove removes a proposal from the storage.
12	Remove(id uint64)
13
14	// Size returns the number of proposals that the storage contains.
15	Size() int
16
17	// Iterate iterates proposals.
18	Iterate(offset, count int, reverse bool, fn func(*Proposal) bool) bool
19}
source

ProposalStorage defines an interface for proposal storages.

type ReadonlyMemberGroup

struct
1type ReadonlyMemberGroup struct {
2	group MemberGroup
3}
source

ReadonlyMemberGroup defines a readonly member group.

Methods on ReadonlyMemberGroup

func GetMeta

method on ReadonlyMemberGroup
1func (g ReadonlyMemberGroup) GetMeta() any
source

GetMeta returns the group metadata.

func Members

method on ReadonlyMemberGroup
1func (g ReadonlyMemberGroup) Members() *ReadonlyMemberStorage
source

Members returns the members that belong to the group.

func Name

method on ReadonlyMemberGroup
1func (g ReadonlyMemberGroup) Name() string
source

Name returns the name of the group.

type ReadonlyMemberGrouping

struct
1type ReadonlyMemberGrouping struct {
2	grouping MemberGrouping
3}
source

ReadonlyMemberGrouping defines a type for storing multiple readonly member groups.

Methods on ReadonlyMemberGrouping

func Get

method on ReadonlyMemberGrouping
1func (g ReadonlyMemberGrouping) Get(name string) (_ *ReadonlyMemberGroup, found bool)
source

Get returns a member group.

func Has

method on ReadonlyMemberGrouping
1func (g ReadonlyMemberGrouping) Has(name string) bool
source

Has checks if a group exists.

func IterateByOffset

method on ReadonlyMemberGrouping
1func (g ReadonlyMemberGrouping) IterateByOffset(offset, count int, fn func(*ReadonlyMemberGroup) bool) bool
source

IterateByOffset iterates all member groups.

func Size

method on ReadonlyMemberGrouping
1func (g ReadonlyMemberGrouping) Size() int
source

Size returns the number of groups that grouping contains.

type ReadonlyMemberStorage

struct
1type ReadonlyMemberStorage struct {
2	storage MemberStorage
3}
source

ReadonlyMemberStorage defines a readonly member storage.

Methods on ReadonlyMemberStorage

func Grouping

method on ReadonlyMemberStorage
1func (s ReadonlyMemberStorage) Grouping() *ReadonlyMemberGrouping
source

Grouping returns member groups.

func Has

method on ReadonlyMemberStorage
1func (s ReadonlyMemberStorage) Has(member address) bool
source

Has checks if a member exists in the storage.

func IterateByOffset

method on ReadonlyMemberStorage
1func (s ReadonlyMemberStorage) IterateByOffset(offset, count int, fn MemberIterFn) bool
source

IterateByOffset iterates members starting at the given offset. The callback can return true to stop iteration.

func Size

method on ReadonlyMemberStorage
1func (s ReadonlyMemberStorage) Size() int
source

Size returns the number of members in the storage.

type ReadonlyVotingRecord

struct
1type ReadonlyVotingRecord struct {
2	votes bptree.BPTree // string(address) -> Vote
3	count bptree.BPTree // string(choice) -> int
4}
source

ReadonlyVotingRecord defines an read only voting record.

Methods on ReadonlyVotingRecord

func GetVote

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) GetVote(user address) (_ Vote, found bool)
source

GetVote returns a vote.

func HasVoted

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) HasVoted(user address) bool
source

HasVoted checks if an account already voted.

func Iterate

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) Iterate(offset, count int, reverse bool, fn VoteIterFn) bool
source

Iterate iterates voting record votes.

func IterateVotesCount

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) IterateVotesCount(fn VotesCountIterFn) bool
source

IterateVotesCount iterates voted choices with the amount of votes submited for each.

func Size

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) Size() int
source

Size returns the total number of votes that record contains.

func VoteCount

method on ReadonlyVotingRecord
1func (r ReadonlyVotingRecord) VoteCount(c VoteChoice) int
source

VoteCount returns the number of votes for a single voting choice.

type Validable

interface
1type Validable interface {
2	// Validate validates that the proposal is valid for the current state.
3	Validate() error
4}
source

Validable defines an interface for proposal definitions that require state validation. Validation is done before execution and normally also during proposal rendering.

type Vote

struct
 1type Vote struct {
 2	// Address is the address of the user that this vote belons to.
 3	Address address
 4
 5	// Choice contains the voted choice.
 6	Choice VoteChoice
 7
 8	// Reason contains an optional reason for the vote.
 9	Reason string
10
11	// Context can store any custom voting values related to the vote.
12	//
13	// Warning: When using context be careful if references/pointers are
14	// assigned to it because they could potentially be accessed anywhere,
15	// which could lead to unwanted indirect modifications.
16	Context any
17}
source

Vote defines a single vote.

type VoteChoice

ident
1type VoteChoice string
source

VoteChoice defines a type for proposal vote choices.

type VoteIterFn

func
1type VoteIterFn func(Vote) (stop bool)
source

VoteIterFn defines a callback to iterate votes.

type VotesCountIterFn

func
1type VotesCountIterFn func(_ VoteChoice, voteCount int) (stop bool)
source

VotesCountIterFn defines a callback to iterate voted choices.

type VotingContext

struct
1type VotingContext struct {
2	VotingRecord ReadonlyVotingRecord
3	Members      ReadonlyMemberStorage
4}
source

VotingContext contains current voting context, which includes a voting record for the votes that has been submitted for a proposal and also the list of DAO members.

type VotingRecord

struct
1type VotingRecord struct {
2	ReadonlyVotingRecord
3}
source

VotingRecord stores accounts that voted and vote choices.

Methods on VotingRecord

func AddVote

method on VotingRecord
1func (r *VotingRecord) AddVote(vote Vote) (updated bool)
source

AddVote adds a vote to the voting record. If a vote for the same user already exists is overwritten.

func Readonly

method on VotingRecord
1func (r VotingRecord) Readonly() ReadonlyVotingRecord
source

Readonly returns a read only voting record.

Imports 8

Source Files 26