PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/daily/governor/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / daily / governor
Files
3 (README)(gnomod.toml)
Exported functions
5
Module
gno.land/r/moul/x/daily/governor/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • governor.gnogno
governor.gnogno
1// Package governor is a simplified on-chain governance realm inspired by2// OpenZeppelin's Governor. Anyone may open a proposal; every address gets a3// single equally-weighted vote (1 address = 1 vote); a proposal succeeds when4// its voting deadline has passed and the "for" tally strictly beats "against".5package governor67import (8	"strconv"9	"strings"1011	"chain"12	"chain/runtime"13	"chain/runtime/unsafe"1415	"gno.land/p/nt/avl/v0"16)1718// votingPeriod is the number of blocks a proposal stays open for voting.19const votingPeriod = int64(100)2021// Vote support values.22const (23	VoteAgainst = 024	VoteFor     = 125	VoteAbstain = 226)2728// Proposal state values.29const (30	StateActive    = "Active"31	StateSucceeded = "Succeeded"32	StateDefeated  = "Defeated"33	StateExecuted  = "Executed"34)3536// Proposal is a single governance proposal.37type Proposal struct {38	ID             int6439	Proposer       address40	Description    string41	SnapshotHeight int6442	Deadline       int6443	For            int6444	Against        int6445	Abstain        int6446	Executed       bool47	votes          *avl.Tree // voter address (string) -> support (int)48}4950var (51	proposals  = avl.NewTree() // id (zero-padded string) -> *Proposal52	nextID     = int64(1)53	totalCount int6454)5556// Propose opens a new proposal and returns its id. The snapshot height and57// deadline are recorded from the current chain height.58func Propose(cur realm, description string) int64 {59	if strings.TrimSpace(description) == "" {60		panic("governor: empty description")61	}62	proposer := unsafe.PreviousRealm().Address()63	h := runtime.ChainHeight()64	id := nextID65	nextID++66	totalCount++6768	p := &Proposal{69		ID:             id,70		Proposer:       proposer,71		Description:    description,72		SnapshotHeight: h,73		Deadline:       h + votingPeriod,74		votes:          avl.NewTree(),75	}76	proposals.Set(idKey(id), p)7778	chain.Emit(79		"ProposalCreated",80		"id", strconv.FormatInt(id, 10),81		"proposer", proposer.String(),82		"deadline", strconv.FormatInt(p.Deadline, 10),83	)84	return id85}8687// CastVote records one vote for the caller on proposal id. support is88// 0=against, 1=for, 2=abstain. One address may vote at most once per proposal,89// and voting is only allowed while the proposal is Active.90func CastVote(cur realm, id int64, support int) {91	p := mustGet(id)92	if computeState(p, runtime.ChainHeight()) != StateActive {93		panic("governor: voting closed")94	}95	if support < VoteAgainst || support > VoteAbstain {96		panic("governor: invalid support value")97	}98	voter := unsafe.PreviousRealm().Address()99	if p.votes.Has(voter.String()) {100		panic("governor: already voted")101	}102	p.votes.Set(voter.String(), support)103104	switch support {105	case VoteFor:106		p.For++107	case VoteAgainst:108		p.Against++109	default:110		p.Abstain++111	}112113	chain.Emit(114		"VoteCast",115		"id", strconv.FormatInt(id, 10),116		"voter", voter.String(),117		"support", strconv.Itoa(support),118	)119}120121// Execute marks a Succeeded proposal as executed. It panics unless the122// proposal has reached the Succeeded state.123func Execute(cur realm, id int64) {124	p := mustGet(id)125	if computeState(p, runtime.ChainHeight()) != StateSucceeded {126		panic("governor: proposal not in Succeeded state")127	}128	p.Executed = true129	chain.Emit("ProposalExecuted", "id", strconv.FormatInt(id, 10))130}131132// State returns the current lifecycle state of proposal id.133func State(id int64) string {134	return computeState(mustGet(id), runtime.ChainHeight())135}136137// computeState is the pure state machine: it decides the state of p at chain138// height h. Kept free of globals so it is unit-testable.139func computeState(p *Proposal, h int64) string {140	if p.Executed {141		return StateExecuted142	}143	if h < p.Deadline {144		return StateActive145	}146	if p.For > p.Against {147		return StateSucceeded148	}149	return StateDefeated150}151152func mustGet(id int64) *Proposal {153	key := idKey(id)154	if !proposals.Has(key) {155		panic("governor: unknown proposal " + strconv.FormatInt(id, 10))156	}157	return proposals.Get(key).(*Proposal)158}159160// idKey returns a zero-padded, lexicographically-sortable key for an id so the161// avl tree iterates proposals in numeric order.162func idKey(id int64) string {163	s := strconv.FormatInt(id, 10)164	const width = 12165	if len(s) >= width {166		return s167	}168	return strings.Repeat("0", width-len(s)) + s169}170171// bar renders a proportional ▓░ progress bar of fixed width.172func bar(value, total int64, width int) string {173	if width <= 0 {174		return ""175	}176	filled := 0177	if total > 0 {178		filled = int((value*int64(width) + total/2) / total)179		if filled > width {180			filled = width181		}182	}183	return strings.Repeat("▓", filled) + strings.Repeat("░", width-filled)184}185186// Render lists all proposals with their tallies and states as Markdown.187func Render(path string) string {188	var b strings.Builder189	b.WriteString("# 🏛️ Governor\n\n")190	b.WriteString("Simplified on-chain governance — 1 address = 1 vote, ")191	b.WriteString("voting period of " + strconv.FormatInt(votingPeriod, 10) + " blocks.\n\n")192193	h := runtime.ChainHeight()194	b.WriteString("Current chain height: **" + strconv.FormatInt(h, 10) + "**\n\n")195196	if totalCount == 0 {197		b.WriteString("_No proposals yet. Call `Propose` to create one._\n")198		return b.String()199	}200201	b.WriteString("Total proposals: **" + strconv.FormatInt(totalCount, 10) + "**\n\n")202203	proposals.Iterate("", "", func(_ string, v interface{}) bool {204		p := v.(*Proposal)205		state := computeState(p, h)206		total := p.For + p.Against + p.Abstain207208		b.WriteString("---\n\n")209		b.WriteString("## #" + strconv.FormatInt(p.ID, 10) + " · " + state + "\n\n")210		b.WriteString("> " + p.Description + "\n\n")211		b.WriteString("- Proposer: `" + p.Proposer.String() + "`\n")212		b.WriteString("- Snapshot height: " + strconv.FormatInt(p.SnapshotHeight, 10) + "\n")213		b.WriteString("- Deadline height: " + strconv.FormatInt(p.Deadline, 10))214		if state == StateActive {215			b.WriteString(" (" + strconv.FormatInt(p.Deadline-h, 10) + " blocks left)")216		}217		b.WriteString("\n\n")218219		b.WriteString("| Choice | Votes | Tally |\n")220		b.WriteString("|---|---|---|\n")221		b.WriteString("| For | " + strconv.FormatInt(p.For, 10) + " | `" + bar(p.For, total, 20) + "` |\n")222		b.WriteString("| Against | " + strconv.FormatInt(p.Against, 10) + " | `" + bar(p.Against, total, 20) + "` |\n")223		b.WriteString("| Abstain | " + strconv.FormatInt(p.Abstain, 10) + " | `" + bar(p.Abstain, total, 20) + "` |\n\n")224225		return false226	})227228	return b.String()229}230

Functions

  • CastVote(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64, support int)

  • Execute(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64)

  • Propose(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, description string) int64

  • Render(path string) string

  • State(id int64) string

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.