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/gov/dao/impl/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
gov / dao / impl
Files
25 (gnomod.toml)
Exported functions
17
Module
gno.land/r/gov/dao/impl/v0
gno
0.9

Files (25)

  • gnomod.tomltoml
  • clamp.gnogno
  • filter.gnogno
  • govdao.gnogno
  • impl.gnogno
  • prop_requests.gnogno
  • render.gnogno
  • types.gnogno
  • clamp_test.gnogno
  • denied_reason_test.gnogno
  • executor_disclosure_filetest.gnogno
  • executor_invocation_authority_filetest.gnogno
  • govdao_execute_proposal_00_filetest.gnogno
  • govdao_execute_proposal_01_filetest.gnogno
  • govdao_execute_proposal_02_filetest.gnogno
  • govdao_execute_proposal_03_filetest.gnogno
  • govdao_test.gnogno
  • render_error_paths_filetest.gnogno
  • stringify_proposal_00_filetest.gnogno
  • title_clamp_filetest.gnogno
  • z_addr_validation_test.gnogno
  • z_denied_reason_store_test.gnogno
  • z_treasury_payment_request_test.gnogno
  • z_unknown_proposal_test.gnogno
  • z_upgrade_request_test.gnogno
  • render.gnogno
    1package impl23import (4	"chain/runtime"5	"strconv"6	"strings"78

    Functions

    • AddMember(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}, addr string)

    • GetInstance(int, rlm 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}) *gno.land/r/gov/dao/impl/v0.GovDAO

    • NewAddMemberRequest(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}, addr string, tier string, portfolio string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewChangeLawRequest(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}, newLaw struct{Supermajority float64}) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewFilterByTier(tier string) struct{Tier string}

    • NewGovDAO() *gno.land/r/gov/dao/impl/v0.GovDAO

    • NewLaw(supermajority float64) struct{Supermajority float64}

    • NewPromoteMemberRequest(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}, addr string, fromTier string, toTier string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewProposalsStatuses() struct{BPTree *gno.land/p/nt/bptree/v0.BPTree}

    • NewRender(d *gno.land/r/gov/dao/impl/v0.GovDAO) *gno.land/r/gov/dao/impl/v0.render

    • NewTreasuryGRC20TokensUpdate(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}, newTokenKeys []string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewTreasuryPaymentRequest(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}, payment interface {BankerID func() string; String func() string}, reason string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewUpgradeDaoImplRequest(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}, newDao interface {ExecuteProposal func(int, .uverse.realm, gno.land/r/gov/dao.ProposalID, gno.land/r/gov/dao.Executor) .uverse.error; PostCreateProposal func(int, .uverse.realm, gno.land/r/gov/dao.ProposalRequest, gno.land/r/gov/dao.ProposalID); PreCreateProposal func(int, .uverse.realm, gno.land/r/gov/dao.ProposalRequest) (.uverse.address, .uverse.error); PreExecuteProposal func(int, .uverse.realm, gno.land/r/gov/dao.ProposalID) (bool, .uverse.error); Render func(.uverse.realm, string, string) string; VoteOnProposal func(int, .uverse.realm, gno.land/r/gov/dao.VoteRequest) .uverse.error}, realmPkg string, reason string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewWithdrawMemberRequest(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}, addr string, reason string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • Render(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}, in string) string

    • StringifyProposal(p *gno.land/r/gov/dao.Proposal) string

    • StringifyVotes(int, rlm 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}, ps *gno.land/r/gov/dao/impl/v0.proposalStatus) 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.

    "gno.land/p/moul/helplink/v0"
    9 "gno.land/p/moul/md/v0"
    10 "gno.land/p/nt/bptree/pager/v0"
    11 "gno.land/p/nt/markdown/sanitize/v0"
    12 "gno.land/p/nt/mux/v0"
    13 "gno.land/p/nt/seqid/v0"
    14 "gno.land/p/nt/ufmt/v0"
    15 "gno.land/r/gov/dao"
    16 "gno.land/r/sys/users"
    17)
    18
    19type render struct {
    20 relativeRealmPath string
    21 router *mux.Router
    22 pssPager *pager.Pager
    23}
    24
    25func NewRender(d *GovDAO) *render {
    26 ren := &render{
    27 pssPager: pager.NewPager(d.pss.BPTree, 5, true),
    28 }
    29
    30 r := mux.NewRouter()
    31
    32 // Handlers use mux's rlm-aware shape: rlm is supplied at RenderRlm
    33 // dispatch time rather than captured at NewRender time. This lets
    34 // downstream crossing reads (dao.GetProposal etc.) use cross(rlm)
    35 // without relying on bare cross or restructuring the router.
    36 r.HandleFuncRlm("", func(_ int, rlm realm, rw *mux.ResponseWriter, req *mux.Request) {
    37 rw.Write(ren.renderActiveProposals(0, rlm, req.RawPath, d))
    38 })
    39
    40 r.HandleFuncRlm("{pid}", func(_ int, rlm realm, rw *mux.ResponseWriter, req *mux.Request) {
    41 rw.Write(ren.renderProposalPage(0, rlm, req.GetVar("pid"), d))
    42 })
    43
    44 r.HandleFuncRlm("{pid}/votes", func(_ int, rlm realm, rw *mux.ResponseWriter, req *mux.Request) {
    45 rw.Write(ren.renderVotesForProposal(0, rlm, req.GetVar("pid"), d))
    46 })
    47
    48 ren.router = r
    49
    50 return ren
    51}
    52
    53func (ren *render) Render(_ int, rlm realm, pkgPath string, path string) string {
    54 relativePath, found := strings.CutPrefix(pkgPath, runtime.ChainDomain())
    55 if !found {
    56 panic(ufmt.Sprintf(
    57 "realm package with unexpected name found: %v in chain domain %v",
    58 pkgPath, runtime.ChainDomain()))
    59 }
    60 ren.relativeRealmPath = relativePath
    61 return ren.router.RenderRlm(0, rlm, path)
    62}
    63
    64func (ren *render) renderActiveProposals(_ int, rlm realm, url string, d *GovDAO) string {
    65 out := "# GovDAO\n"
    66 out += "## Members\n"
    67 out += "[> Go to Memberstore <](/r/gov/dao/memberstore/v0)\n"
    68 out += "## Proposals\n"
    69 page, perr := ren.pssPager.GetPageByPath(url)
    70 if perr != nil {
    71 // A query url.Parse rejects (e.g. a control byte) is the caller's own
    72 // malformed input; render the default first page instead of aborting
    73 // this read-only render. ParseQuery already tolerates bad page/size
    74 // values, so every currently-working input is unaffected.
    75 page = ren.pssPager.GetPage(1)
    76 }
    77 if len(page.Items) == 0 {
    78 out += "\nNo proposals yet.\n\n"
    79 return out
    80 }
    81
    82 for _, item := range page.Items {
    83 seqpid, err := seqid.FromString(item.Key)
    84 if err != nil {
    85 continue
    86 }
    87 out += ren.renderProposalListItem(0, rlm, ufmt.Sprintf("%v", int64(seqpid)), d)
    88 out += "---\n\n"
    89 }
    90
    91 out += page.Picker("")
    92
    93 return out
    94}
    95
    96func (ren *render) renderProposalPage(_ int, rlm realm, sPid string, d *GovDAO) string {
    97 pid, err := strconv.ParseInt(sPid, 10, 64)
    98 if err != nil {
    99 // err echoes the caller's raw pid segment (strconv quotes it but leaves
    100 // markdown/HTML metachars); escape+clamp it like every other untrusted
    101 // slot on this page, since Render is reachable unauthenticated.
    102 return ufmt.Sprintf("# Error: Invalid proposal ID format.\n\n\n%s\n\n", md.EscapeText(clampField(err.Error(), maxRenderedError)))
    103 }
    104
    105 p, err := dao.GetProposal(dao.ProposalID(pid))
    106 if err != nil {
    107 return ufmt.Sprintf("# Proposal not found\n\n%s", err.Error())
    108 }
    109
    110 // pid is user-supplied and the proposal itself lives on the proxy, so
    111 // GetProposal can succeed for a proposal this implementation has no status
    112 // for — the same post-upgrade case PreExecuteProposal guards (statuses live
    113 // on the instance, so a fresh instance has none). Without this the page
    114 // panics at ps.String below. renderProposalListItem needs no such guard:
    115 // its pids are iterated out of pss itself, so a status always exists.
    116 ps := d.pss.GetStatus(dao.ProposalID(pid))
    117 if ps == nil {
    118 return ufmt.Sprintf("# Proposal #%v not available\n\nThis proposal was not created by the current govDAO implementation, so it has no voting status here.", pid)
    119 }
    120
    121 out := ufmt.Sprintf("## Prop #%v - %v\n", pid, md.EscapeText(clampField(p.Title(), maxRenderedTitle)))
    122 out += "Author: " + tryResolveAddr(p.Author()) + "\n\n"
    123
    124 out += p.Description()
    125 out += "\n\n"
    126
    127 // Add executor metadata if available
    128 if p.ExecutorString() != "" {
    129 out += ufmt.Sprintf(`This proposal contains the following metadata:
    130
    131%s
    132
    133`, p.ExecutorString())
    134 }
    135
    136 // Disclosed independently of the description: this names the realm whose
    137 // code runs if the proposal passes. Sharing the gate above hid it for every
    138 // proposal built with an empty executor description — 16 call sites across
    139 // 7 production realms, nearly all r/sys/* governance actions.
    140 //
    141 // Escaped, not trusted: CreationRealm() is dispatched through the public
    142 // dao.Executor interface, so only SimpleExecutor's value is VM-captured;
    143 // a third-party executor returns any string it likes.
    144 // Guarded on the sanitized value, not the raw one: InlineCode returns ""
    145 // for input that strips to nothing (bidi/zero-width only), and TrimSpace
    146 // catches plain whitespace, so neither prints a label with nothing after
    147 // it. This is tidiness, not a boundary: a zero-width/space mixture still
    148 // renders an empty-looking span, and a hostile executor can always return
    149 // a plausible-looking lie. The security property is the escaping below.
    150 if cr := sanitize.InlineCode(strings.TrimSpace(clampField(p.ExecutorCreationRealm(), maxRenderedRealm))); cr != "" {
    151 out += ufmt.Sprintf("Executor created in: %s\n", cr)
    152 out += "\n\n"
    153 }
    154
    155 out += "\n\n---\n\n"
    156 out += ps.String(0, rlm)
    157 out += "\n"
    158 out += ufmt.Sprintf("[Detailed voting list](%v:%v/votes)", ren.relativeRealmPath, pid)
    159 out += "\n\n---\n\n"
    160
    161 out += renderActionBar(ufmt.Sprintf("%v", pid))
    162
    163 return out
    164}
    165
    166func (ren *render) renderProposalListItem(_ int, rlm realm, sPid string, d *GovDAO) string {
    167 pid, err := strconv.ParseInt(sPid, 10, 64)
    168 if err != nil {
    169 // err echoes the caller's raw pid segment (strconv quotes it but leaves
    170 // markdown/HTML metachars); escape+clamp it like every other untrusted
    171 // slot on this page, since Render is reachable unauthenticated.
    172 return ufmt.Sprintf("# Error: Invalid proposal ID format.\n\n\n%s\n\n", md.EscapeText(clampField(err.Error(), maxRenderedError)))
    173 }
    174
    175 p, err := dao.GetProposal(dao.ProposalID(pid))
    176 if err != nil {
    177 return ufmt.Sprintf("# Proposal not found\n\n%s\n\n", err.Error())
    178 }
    179
    180 ps := d.pss.GetStatus(dao.ProposalID(pid))
    181 out := ufmt.Sprintf("### [Prop #%v - %v](%v:%v)\n", pid, md.EscapeText(clampField(p.Title(), maxRenderedTitle)), ren.relativeRealmPath, pid)
    182 out += ufmt.Sprintf("Author: %s\n\n", tryResolveAddr(p.Author()))
    183
    184 out += "Status: " + getPropStatus(ps)
    185 out += "\n\n"
    186
    187 out += "Tiers eligible to vote: "
    188 out += strings.Join(ps.TiersAllowedToVote, ", ")
    189
    190 out += "\n\n"
    191 return out
    192}
    193
    194func (ren *render) renderVotesForProposal(_ int, rlm realm, sPid string, d *GovDAO) string {
    195 pid, err := strconv.ParseInt(sPid, 10, 64)
    196 if err != nil {
    197 // err echoes the caller's raw pid segment (strconv quotes it but leaves
    198 // markdown/HTML metachars); escape+clamp it like every other untrusted
    199 // slot on this page, since Render is reachable unauthenticated.
    200 return ufmt.Sprintf("# Error: Invalid proposal ID format.\n\n\n%s\n\n", md.EscapeText(clampField(err.Error(), maxRenderedError)))
    201 }
    202
    203 ps := d.pss.GetStatus(dao.ProposalID(pid))
    204 if ps == nil {
    205 return ufmt.Sprintf("# Proposal not found\n\nProposal %v does not exist.", pid)
    206 }
    207
    208 out := ""
    209 out += ufmt.Sprintf("# Proposal #%v - Vote List\n\n", pid)
    210 out += StringifyVotes(0, rlm, ps)
    211
    212 return out
    213}
    214
    215func isPropActive(ps *proposalStatus) bool {
    216 return !ps.Accepted && !ps.Denied
    217}
    218
    219func getPropStatus(ps *proposalStatus) string {
    220 if ps == nil {
    221 return "UNKNOWN"
    222 }
    223 if ps.Accepted {
    224 return "ACCEPTED"
    225 } else if ps.Denied {
    226 return "REJECTED"
    227 }
    228 return "ACTIVE"
    229}
    230
    231func renderActionBar(sPid string) string {
    232 out := "### Actions\n"
    233
    234 proxy := helplink.Realm("gno.land/r/gov/dao")
    235 out += proxy.Func("Vote YES", "MustVoteOnProposalSimple", "pid", sPid, "option", "YES") + " | "
    236 out += proxy.Func("Vote NO", "MustVoteOnProposalSimple", "pid", sPid, "option", "NO") + " | "
    237 out += proxy.Func("Vote ABSTAIN", "MustVoteOnProposalSimple", "pid", sPid, "option", "ABSTAIN")
    238
    239 out += "\n\n"
    240 out += "WARNING: Please double check transaction data before voting."
    241 return out
    242}
    243
    244// tryResolveAddr renders the author/voter as a username link. RenderLink
    245// interpolates the username raw into "[@name](/u/name)" (r/sys/users), so this
    246// is markdown-safe ONLY because r/sys/users validateName restricts names to
    247// ^[a-z][a-z0-9]*([_-][a-z0-9]+)*$ (max 64) — no markdown/HTML metachar. If that
    248// charset ever loosens, this line and writeVotes in types.gno need escaping.
    249func tryResolveAddr(addr address) string {
    250 userData := users.ResolveAddress(addr)
    251 if userData == nil {
    252 return addr.String()
    253 }
    254 return userData.RenderLink("")
    255}
    256