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
  • executor_disclosure_filetest.gnogno
    1// PKGPATH: gno.land/r/test/disclosure2package disclosure34// Covers the executor-disclosure changes in an isolated realm. The unit tests5// in the impl package share proposal ids across files (govdao_test.gno asserts6// a hard-coded id) and swap the DAO implementation partway through, so these7// live here instead.

    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.

    8
    9import (
    10 "strings"
    11 "testing"
    12
    13 "gno.land/r/gov/dao"
    14 "gno.land/r/gov/dao/impl/v0"
    15 "gno.land/r/gov/dao/memberstore/v0"
    16)
    17
    18const user address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
    19
    20func init(cur realm) {
    21 memberstore.Get(0, cur).DeleteAll()
    22 memberstore.Get(0, cur).SetTier(memberstore.T1)
    23 memberstore.Get(0, cur).SetMember(memberstore.T1, user, memberstore.NewMember(3))
    24 dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(impl.NewGovDAO(), nil))
    25}
    26
    27// hostileExecutor implements dao.Executor directly rather than through
    28// NewSimpleExecutor, which is what lets it choose its own CreationRealm.
    29// CreationRealm() is dispatched through the public dao.Executor interface, so
    30// only SimpleExecutor's value is VM-supplied from rlm.PkgPath().
    31type hostileExecutor struct{}
    32
    33func (e *hostileExecutor) Execute(cur realm) error { return nil }
    34
    35func (e *hostileExecutor) String() string { return "" }
    36
    37func (e *hostileExecutor) CreationRealm() string {
    38 return "gno.land/r/sys/params\n\n### Stats\n\n- **PROPOSAL HAS BEEN ACCEPTED**\n- YES PERCENT: 100%\n\n---\n"
    39}
    40
    41// blankExecutor's CreationRealm is non-empty but strips to nothing:
    42// sanitize.InlineCode removes bidi and zero-width characters, so it returns "".
    43type blankExecutor struct{}
    44
    45func (e *blankExecutor) Execute(cur realm) error { return nil }
    46
    47func (e *blankExecutor) String() string { return "" }
    48
    49func (e *blankExecutor) CreationRealm() string { return "\u200b\u200b\u202e" }
    50
    51// whitespaceExecutor covers the other half of the guard: plain whitespace,
    52// which InlineCode would otherwise wrap in a padded, empty-looking span.
    53type whitespaceExecutor struct{}
    54
    55func (e *whitespaceExecutor) Execute(cur realm) error { return nil }
    56
    57func (e *whitespaceExecutor) String() string { return "" }
    58
    59func (e *whitespaceExecutor) CreationRealm() string { return " \t " }
    60
    61// hugeExecutor computes a very large CreationRealm while storing nothing.
    62// Sanitizing costs ~11,310 gas/byte and render is reachable unauthenticated
    63// under a 3,000,000,000 gas cap, so this must be clamped before escaping.
    64type hugeExecutor struct{}
    65
    66func (e *hugeExecutor) Execute(cur realm) error { return nil }
    67
    68func (e *hugeExecutor) String() string { return "" }
    69
    70func (e *hugeExecutor) CreationRealm() string { return strings.Repeat("z", 20000) }
    71
    72// fenceExecutor attacks the code span itself. Section 4 below sends backticks
    73// through the grant sentence, but that path escapes the value directly. The
    74// creation realm is clamped first and escaped second, so it needs its own
    75// case: the fence is chosen after the cut, and must still outscan whatever
    76// backticks survived it. The run here is two long, so a two-backtick fence
    77// would be closed by the payload.
    78type fenceExecutor struct{}
    79
    80func (e *fenceExecutor) Execute(cur realm) error { return nil }
    81
    82func (e *fenceExecutor) String() string { return "" }
    83
    84func (e *fenceExecutor) CreationRealm() string { return "gno.land/r/evil`` **INJECTED**" }
    85
    86// wsExecutor returns a large run of spaces. TrimSpace used to run before the
    87// clamp, so it scanned every byte of whatever the executor returned: 250KB of
    88// spaces cost 1,368,719,824 gas to render nothing at all, and 560KB cost
    89// 3,048,904,520 — past the query cap, so the page could not be rendered by
    90// anyone. Clamping first bounds the scan; the same 560KB now costs 16,657,792.
    91type wsExecutor struct{}
    92
    93func (e *wsExecutor) Execute(cur realm) error { return nil }
    94
    95func (e *wsExecutor) String() string { return "" }
    96
    97func (e *wsExecutor) CreationRealm() string { return strings.Repeat(" ", 20000) }
    98
    99func main(cur realm) {
    100 testing.SetOriginCaller(user)
    101
    102 // 1. An executor with NO description. The creation realm used to share the
    103 // `ExecutorString() != ""` gate with the description, so it was hidden for
    104 // every such proposal — 16 call sites across 7 production realms.
    105 // SetRealm first: NewSimpleExecutor captures rlm.PkgPath(), which is empty
    106 // outside a code realm.
    107 testing.SetRealm(testing.NewCodeRealm("gno.land/r/template/silent"))
    108 silent := dao.NewSimpleExecutor(0, cur, func(realm) error { return nil }, "")
    109
    110 testing.SetRealm(testing.NewUserRealm(user))
    111 pid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    112 "Silent", "A proposal whose executor has no description", silent))
    113 out := dao.Render(cross(cur), pid.String())
    114
    115 println("empty-description proposal discloses creation realm:",
    116 strings.Contains(out, "Executor created in: `gno.land/r/template/silent`"))
    117 println("and prints no empty metadata block:",
    118 !strings.Contains(out, "This proposal contains the following metadata"))
    119
    120 // 2. CreationRealm() is dispatched through the public dao.Executor
    121 // interface, so a third-party executor picks its own value — and the
    122 // disclosure now renders for every proposal. InlineCode does not delete the
    123 // hostile text; it folds it onto one line inside a code span, where it can
    124 // no longer forge page structure. So assert structure, not absence.
    125 hpid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    126 "Hostile", "A proposal whose executor forges page structure", &hostileExecutor{}))
    127 hout := dao.Render(cross(cur), hpid.String())
    128
    129 println("only the genuine Stats heading exists:",
    130 strings.Count(hout, "\n### Stats") == 1)
    131 println("no forged acceptance line:",
    132 !strings.Contains(hout, "\n- **PROPOSAL HAS BEEN ACCEPTED**"))
    133 println("no forged tally line:",
    134 !strings.Contains(hout, "\n- YES PERCENT: 100%"))
    135 println("genuine tally and status still render:",
    136 strings.Contains(hout, "\n- YES PERCENT: 0%") &&
    137 strings.Contains(hout, "- **Proposal is open for votes**"))
    138 // One line, inside a code span: the newlines are folded to spaces, so none
    139 // of the payload can start a block. (No pad space before the value now —
    140 // TrimSpace removes the payload's trailing newline, so InlineCode does not
    141 // need to pad the fence.)
    142 println("hostile value is confined to one code-span line:",
    143 strings.Contains(hout, "Executor created in: `gno.land/r/sys/params ### Stats"))
    144
    145 // 3. The upgrade proposal rewrites AllowedDAOs — the sole authorization for
    146 // replacing the implementation, mutating the member store and moving
    147 // treasury funds. It used to carry an empty description, so the realm
    148 // receiving that authority appeared nowhere a voter would read.
    149 upid := dao.MustCreateProposal(cross(cur),
    150 impl.NewUpgradeDaoImplRequest(cross(cur), impl.NewGovDAO(), "gno.land/r/gov/dao/v1/impl", "reason"))
    151 uout := dao.Render(cross(cur), upid.String())
    152
    153 println("upgrade proposal states the grant:",
    154 strings.Contains(uout, "may replace the implementation, mutate the member store, or move treasury funds"))
    155 println("upgrade proposal names the granted realm:",
    156 strings.Contains(uout, "`gno.land/r/gov/dao/v1/impl`"))
    157
    158 // 4. realmPkg is caller-supplied and lands inside a code span. md.EscapeText
    159 // was wrong there: CommonMark 6.1 does not process backslash escapes inside
    160 // code spans, so it rendered visible backslashes, and a backtick closed the
    161 // span early. InlineCode widens the fence instead, so the payload stays
    162 // inside it as literal text.
    163 bpid := dao.MustCreateProposal(cross(cur),
    164 impl.NewUpgradeDaoImplRequest(cross(cur), impl.NewGovDAO(),
    165 "gno.land/r/x` **PROPOSAL HAS BEEN ACCEPTED** `", "reason"))
    166 bout := dao.Render(cross(cur), bpid.String())
    167
    168 // The payload's own backtick sits INSIDE a widened `` fence, so it renders
    169 // as literal code rather than closing the span and freeing the bold text.
    170 println("fence widened to contain the backtick:",
    171 strings.Contains(bout, "`` gno.land/r/x` **PROPOSAL HAS BEEN ACCEPTED** ` ``"))
    172 println("no forged acceptance line from the breakout attempt:",
    173 !strings.Contains(bout, "\n- **PROPOSAL HAS BEEN ACCEPTED**"))
    174 println("no visible backslashes in the path:",
    175 !strings.Contains(bout, "gno\\.land"))
    176
    177 // 4b. Guarding the raw value would print the label with nothing after it
    178 // for a creation realm that sanitizes away entirely.
    179 zpid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    180 "Blank", "A proposal whose creation realm strips to nothing", &blankExecutor{}))
    181 zout := dao.Render(cross(cur), zpid.String())
    182
    183 println("a creation realm that strips to nothing prints no bare label:",
    184 !strings.Contains(zout, "Executor created in:"))
    185
    186 wpid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    187 "Whitespace", "A proposal whose creation realm is only whitespace", &whitespaceExecutor{}))
    188 println("a whitespace-only creation realm prints no bare label:",
    189 !strings.Contains(dao.Render(cross(cur), wpid.String()), "Executor created in:"))
    190
    191 hupid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    192 "Huge", "A proposal whose creation realm is enormous", &hugeExecutor{}))
    193 hurendered := dao.Render(cross(cur), hupid.String())
    194 // The truncation marker must sit INSIDE the code span, so the value ends
    195 // with its closing fence. That is what proves the clamp ran before the
    196 // escaping and not after. Cutting an already-escaped value slices the
    197 // closing fence off and leaves the span hanging open, and a length check
    198 // alone cannot tell the two apart — both produce a short string ending in
    199 // the marker.
    200 println("an enormous creation realm is clamped before escaping:",
    201 len(hurendered) < 2000 && strings.Contains(hurendered, "… truncated`"))
    202
    203 // 4c. The same breakout attempt through the creation realm, which is
    204 // clamped before it is escaped. The fence must be sized from the clamped
    205 // string, so it widens to three backticks and the payload stays literal.
    206 fpid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    207 "Fence", "A proposal whose creation realm tries to close the code span", &fenceExecutor{}))
    208 fout := dao.Render(cross(cur), fpid.String())
    209
    210 println("fence outscans the payload's backtick run:",
    211 strings.Contains(fout, "Executor created in: ```gno.land/r/evil`` **INJECTED**```"))
    212 println("no bold text escapes the code span:",
    213 !strings.Contains(fout, "\n**INJECTED**"))
    214
    215 // 4d. A large all-whitespace creation realm. Clamping before trimming is
    216 // what bounds the work here, and the marker is how the test can tell: cut
    217 // first and the marker survives the trim, so the label renders. Trim first
    218 // and the value collapses to nothing, printing no label — and the trim has
    219 // already walked every byte the executor produced.
    220 wpid2 := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
    221 "BigWhitespace", "A proposal whose creation realm is a huge run of spaces", &wsExecutor{}))
    222 wout2 := dao.Render(cross(cur), wpid2.String())
    223
    224 println("a huge whitespace creation realm is clamped before trimming:",
    225 strings.Contains(wout2, "Executor created in: `… truncated`"))
    226
    227 // 5. Proposals live on the proxy but their voting status lives on the
    228 // GovDAO instance, so replacing the implementation leaves earlier
    229 // proposals renderable but statusless. renderProposalPage took a
    230 // user-supplied pid and dereferenced that nil status.
    231 testing.SetRealm(testing.NewCodeRealm("gno.land/r/gov/dao/impl/v0"))
    232 dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(impl.NewGovDAO(), nil))
    233
    234 testing.SetRealm(testing.NewUserRealm(user))
    235 println("a proposal orphaned by an upgrade renders instead of panicking:",
    236 strings.Contains(dao.Render(cross(cur), pid.String()), "not available"))
    237}
    238
    239// Output:
    240// empty-description proposal discloses creation realm: true
    241// and prints no empty metadata block: true
    242// only the genuine Stats heading exists: true
    243// no forged acceptance line: true
    244// no forged tally line: true
    245// genuine tally and status still render: true
    246// hostile value is confined to one code-span line: true
    247// upgrade proposal states the grant: true
    248// upgrade proposal names the granted realm: true
    249// fence widened to contain the backtick: true
    250// no forged acceptance line from the breakout attempt: true
    251// no visible backslashes in the path: true
    252// a creation realm that strips to nothing prints no bare label: true
    253// a whitespace-only creation realm prints no bare label: true
    254// an enormous creation realm is clamped before escaping: true
    255// fence outscans the payload's backtick run: true
    256// no bold text escapes the code span: true
    257// a huge whitespace creation realm is clamped before trimming: true
    258// a proposal orphaned by an upgrade renders instead of panicking: true
    259