Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (gno/govdao): handle T3 abstention in govdao condition to match T2 adding specification #1504

Merged
merged 29 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
52fd5ce
feat: export functions daokit
MikaelVallenet Feb 11, 2025
8114e90
feat: add t1 & t2 conditions
MikaelVallenet Feb 11, 2025
f9ed92b
feat: update
MikaelVallenet Feb 12, 2025
c27a77a
feat: add messages
MikaelVallenet Feb 12, 2025
3929c8d
feat: update
MikaelVallenet Feb 13, 2025
c4439c1
fix: dao
MikaelVallenet Feb 13, 2025
b52ef34
fix: dao
MikaelVallenet Feb 13, 2025
8f42eb7
feat: add invitations system for T3
MikaelVallenet Feb 13, 2025
d697d41
feat: add withdrawal mechanism for T3
MikaelVallenet Feb 13, 2025
84e0342
feat: add limit size membership for T2
MikaelVallenet Feb 14, 2025
8c2416e
feat: rename msg
MikaelVallenet Feb 14, 2025
4fa1ed6
chore: up
MikaelVallenet Feb 14, 2025
d4cf516
feat: add configurables roles for govdao
MikaelVallenet Feb 14, 2025
48a3253
feat: wip adapt govdao condition
MikaelVallenet Feb 15, 2025
db0f641
feat: merge main
MikaelVallenet Feb 15, 2025
fd61c96
feat: merge refactor and adapt code
MikaelVallenet Feb 15, 2025
d246194
feat: merge main
MikaelVallenet Feb 15, 2025
f4a1015
fix: review
MikaelVallenet Feb 15, 2025
c17d5db
fix: enhance comments
MikaelVallenet Feb 15, 2025
5b23f8a
Merge branch 'dev/gno/gov-dao-t3-membership' into dev/gno/handle-t3-a…
MikaelVallenet Feb 15, 2025
5863cd9
fix: use roles
MikaelVallenet Feb 15, 2025
9a87559
Merge branch 'dev/gno/gov-dao-t3-membership' into dev/gno/handle-t3-a…
MikaelVallenet Feb 15, 2025
d0014b3
feat: adapt govdao conditions
MikaelVallenet Feb 15, 2025
de9c380
feat: abstain T3 from voting
MikaelVallenet Feb 15, 2025
8c3a02a
feat: adapt test
MikaelVallenet Feb 17, 2025
a4f4b2d
fix: test
MikaelVallenet Feb 17, 2025
8fff4a8
feat: merge main
MikaelVallenet Feb 17, 2025
fd485b4
fix: adapt to latest changes
MikaelVallenet Feb 17, 2025
f360da2
fix: remove useless duplicate declaration
MikaelVallenet Feb 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 42 additions & 25 deletions gno/p/daocond/cond_govdao.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package daocond

import (
"errors"
"strconv"
"strings"

"gno.land/p/demo/json"
"gno.land/p/demo/ufmt"
)

func GovDaoCondThreshold(threshold float64, hasRoleFn func(memberId string, role string) bool, usersWithRoleCountFn func(role string) uint32) Condition {
var roleWeights = []float64{3.0, 2.0, 1.0}

func GovDaoCondThreshold(threshold float64, roles []string, hasRoleFn func(memberId string, role string) bool, usersWithRoleCountFn func(role string) uint32) Condition {
if threshold <= 0 || threshold > 1 {
panic(errors.New("invalid threshold"))
}
Expand All @@ -17,15 +21,20 @@ func GovDaoCondThreshold(threshold float64, hasRoleFn func(memberId string, role
if hasRoleFn == nil {
panic(errors.New("nil hasRoleFn"))
}
if len(roles) > 3 {
panic("the govdao condition handles at most 3 roles")
}
return &govDaoCondThreshold{
threshold: threshold,
roles: roles,
hasRoleFn: hasRoleFn,
usersWithRoleCountFn: usersWithRoleCountFn,
}
}

type govDaoCondThreshold struct {
threshold float64
roles []string
hasRoleFn func(memberId string, role string) bool
usersWithRoleCountFn func(role string) uint32
}
Expand All @@ -36,9 +45,13 @@ func (m *govDaoCondThreshold) NewState() State {
}
}

// {threshold}% of {totalvotingpower} total voting power following these ({t1power} - T1, {t2power} T2, {t3power} T3)
func (m *govDaoCondThreshold) Render() string {
return ufmt.Sprintf("%g%% of total voting power (3.0 / T1, 2.0 / T2, 1.0 / T3)*", m.threshold*100)
rolePowers := []string{}
for i, role := range m.roles {
weight := strconv.FormatFloat(roleWeights[i], 'f', 2, 64) // ufmt.Sprintf("%.2f", ...) is not working
rolePowers = append(rolePowers, ufmt.Sprintf("%s => %s power", role, weight))
}
return ufmt.Sprintf("%g%% of total voting power | %s", m.threshold*100, strings.Join(rolePowers, " | "))
}

func (m *govDaoCondThreshold) RenderJSON() *json.Node {
Expand All @@ -62,16 +75,20 @@ func (m *govDaoCondThresholdState) HandleEvent(_ Event, _ map[string]Vote) {
}
func (m *govDaoCondThresholdState) RenderJSON(votes map[string]Vote) *json.Node {
vPowers, totalPower := m.computeVotingPowers()
return json.ObjectNode("", map[string]*json.Node{
rolePowers := []string{}
for _, role := range m.cond.roles {
weight := strconv.FormatFloat(vPowers[role], 'f', 2, 64) // ufmt.Sprintf("%.2f", ...) is not working
rolePowers = append(rolePowers, ufmt.Sprintf("%s => %s power", role, weight))
}
jsonData := json.ObjectNode("", map[string]*json.Node{
"type": json.StringNode("", "govdao-threshold"),
"treshold": json.NumberNode("", m.cond.threshold),
"tier1VotingPower": json.NumberNode("", vPowers[roleT1]),
"tier2VotingPower": json.NumberNode("", vPowers[roleT2]),
"tier3VotingPower": json.NumberNode("", vPowers[roleT3]),
"threshold": json.NumberNode("", m.cond.threshold),
"powerSplit": json.StringNode("", strings.Join(rolePowers, " | ")),
"totalYes": json.NumberNode("", m.yesRatio(votes)),
"votingPowerNeeded": json.NumberNode("", m.cond.threshold*totalPower),
"totalVotingPower": json.NumberNode("", totalPower),
})
return jsonData
}

var _ State = (*govDaoCondThresholdState)(nil)
Expand All @@ -88,15 +105,15 @@ func (m *govDaoCondThresholdState) yesRatio(votes map[string]Vote) float64 {
if vote != VoteYes {
continue
}
tier := m.getUserTier(userID)
tier := m.getUserRole(userID)

totalYes += votingPowersByTier[tier]
}
return totalYes / totalPower
}

func (m *govDaoCondThresholdState) getUserTier(userID string) string {
for _, role := range []string{roleT1, roleT2, roleT3} {
func (m *govDaoCondThresholdState) getUserRole(userID string) string {
for _, role := range m.cond.roles {
if m.cond.hasRoleFn(userID, role) {
return role
}
Expand All @@ -105,16 +122,22 @@ func (m *govDaoCondThresholdState) getUserTier(userID string) string {
}

func (m *govDaoCondThresholdState) computeVotingPowers() (map[string]float64, float64) {
totalT1s := float64(m.cond.usersWithRoleCountFn(roleT1))
totalT2s := float64(m.cond.usersWithRoleCountFn(roleT2))
totalT3s := float64(m.cond.usersWithRoleCountFn(roleT3))
votingPowers := map[string]float64{
roleT1: 3.0,
roleT2: computePower(totalT1s, totalT2s, 2.0),
roleT3: computePower(totalT1s, totalT3s, 1.0),
votingPowers := make(map[string]float64)
totalPower := 0.0
countsMembersPerRole := make(map[string]float64)

for _, role := range m.cond.roles {
countsMembersPerRole[role] = float64(m.cond.usersWithRoleCountFn(role))
}

totalPower := votingPowers[roleT1]*totalT1s + votingPowers[roleT2]*totalT2s + votingPowers[roleT3]*totalT3s
for i, role := range m.cond.roles {
if i == 0 {
votingPowers[role] = roleWeights[0] // Highest tier always gets max power (3.0)
} else {
votingPowers[role] = computePower(countsMembersPerRole[m.cond.roles[0]], countsMembersPerRole[role], roleWeights[i])
}
totalPower += votingPowers[role] * countsMembersPerRole[role]
}

return votingPowers, totalPower
}
Expand All @@ -138,9 +161,3 @@ func computePower(T1, Tn, maxPower float64) float64 {
}
return computedPower
}

const (
roleT1 = "T1"
roleT2 = "T2"
roleT3 = "T3"
)
Loading
Loading