README.md
5.68 Kb ยท 200 lines
daocond: Stateless Condition Engine for DAO Governance
daocond is a Gnolang package that provides a stateless condition engine for evaluating DAO proposal execution. It serves as the decision-making core of the daokit framework, determining whether proposals should be executed based on configurable governance rules.
Core Interfaces
Condition Interface
1type Condition interface {
2 // Eval - checks if the condition is satisfied based on current votes
3 Eval(ballot Ballot) bool
4
5 // Signal - returns a value from 0.0 to 1.0 indicating progress toward satisfaction
6 Signal(ballot Ballot) float64
7
8 Render() string // returns a representation of the condition
9 RenderWithVotes(ballot Ballot) string // returns a representation with vote context
10}
Ballot Interface
1type Ballot interface {
2 Vote(voter string, vote Vote) // allows a user to vote on a proposal
3 Get(voter string) Vote // returns the vote of a specific user
4
5 Total() int // returns the total number of votes cast
6
7 Iterate(fn func(voter string, vote Vote) bool) // iterates over all votes
8}
Vote Types
1type Vote int
2
3const (
4 VoteAbstain Vote = iota // Neutral vote
5 VoteNo // Against the proposal
6 VoteYes // In favor of the proposal
7)
Built-in Conditions
daocond provides three core condition types for common governance scenarios:
1// MembersThreshold - Requires a fraction of all DAO members to approve
2func MembersThreshold(threshold float64, isMemberFn func(string) bool, membersCountFn func() uint64) Condition
3
4// RoleThreshold - Requires a percentage of role holders to approve
5func RoleThreshold(threshold float64, role string, hasRoleFn func(string, string) bool, roleCountFn func(string) uint32) Condition
6
7// RoleCount - Requires a minimum number of role holders to approve
8func RoleCount(count uint64, role string, hasRoleFn func(string, string) bool) Condition
Usage Examples:
1// Require 60% of all members
2memberMajority := daocond.MembersThreshold(0.6, store.IsMember, store.MembersCount)
3
4// Require 50% of contributor
5adminApproval := daocond.RoleThreshold(0.5, "contributor", store.HasRole, store.RoleCount)
6
7// Require at least 2 core-contributor
8treasurerApproval := daocond.RoleCount(2, "core-contributor", store.HasRole)
Logical Composition
Combine conditions using logical operators to create complex governance rules:
1// And - All conditions must be satisfied
2func And(conditions ...Condition) Condition {...}
3
4// Or - At least one condition must be satisfied
5func Or(conditions ...Condition) Condition {...}
Examples:
1// Require BOTH admin majority AND treasurer approval
2strictGovernance := daocond.And(
3 daocond.RoleThreshold(0.5, "contributor", store.HasRole, store.RoleCount),
4 daocond.RoleCount(1, "treasurer", store.HasRole),
5)
6
7// Require EITHER treasurer majority OR unanimous core-contributor approval
8flexibleGovernance := daocond.Or(
9 daocond.RoleThreshold(0.5, "treasurer", store.HasRole, store.RoleCount),
10 daocond.RoleThreshold(1.0, "core-contributor", store.HasRole, store.RoleCount),
11)
Creating Custom Conditions
Implement the Condition interface to create custom governance rules:
1type customCondition struct {
2 // Your custom fields
3}
4
5func (c *customCondition) Eval(ballot daocond.Ballot) bool {
6 // Implement your evaluation logic
7 return true
8}
9
10func (c *customCondition) Signal(ballot daocond.Ballot) float64 {
11 // Return progress from 0.0 to 1.0
12 return 0.5
13}
14
15func (c *customCondition) Render() string {
16 return "Custom condition description"
17}
18
19func (c *customCondition) RenderWithVotes(ballot daocond.Ballot) string {
20 return "Custom condition with current vote status"
21}
Usage Examples
Basic Usage
1import "gno.land/p/samcrew/daocond"
2
3// Create a simple majority condition
4condition := daocond.MembersThreshold(0.5, store.IsMember, store.MembersCount)
5
6// Evaluate the condition against a ballot
7if condition.Eval(ballot) {
8 // Proposal meets the condition requirements
9 executeProposal()
10}
11
12// Check progress toward satisfaction
13progress := condition.Signal(ballot) // Returns 0.0 to 1.0
Complex Governance Rules
1// Multi-tier approval system
2governance := daocond.And(
3 // Require 30% of all members
4 daocond.MembersThreshold(0.3, store.IsMember, store.MembersCount),
5
6 // AND at least 2 core-contributor approvals
7 daocond.RoleCount(2, "core-contributor", store.HasRole),
8
9 // AND either CTO approval OR finance team majority
10 daocond.Or(
11 daocond.RoleCount(1, "CTO", store.HasRole),
12 daocond.RoleThreshold(0.5, "finance", store.HasRole, store.RoleCount),
13 ),
14)
Integration with daokit
daocond is designed to work seamlessly with:
1import (
2 "gno.land/p/samcrew/daocond"
3 "gno.land/p/samcrew/daokit"
4)
5
6// Define conditions for different types of proposals
7treasuryCondition := daocond.And(
8 daocond.RoleCount(1, "treasurer", store.HasRole),
9 daocond.MembersThreshold(0.6, store.IsMember, store.MembersCount),
10)
11
12// Use in resource registration
13resource := daokit.Resource{
14 Handler: treasuryHandler,
15 Condition: treasuryCondition,
16 DisplayName: "Treasury Management",
17 Description: "Proposals for treasury operations",
18}
For complete examples and interactive demos, see the /r/samcrew/daodemo/custom_condition realms.
Part of the daokit framework for building decentralized autonomous organizations in gnolang.