1// PKGPATH: gno.land/r/test/titleclamp2package titleclamp34// A proposal title is attacker-chosen (by a member) and is escaped on two5// pages: the proposal page and the list page. Escaping costs about 6,990 gas a6// byte, and the list page escapes one title per proposal shown, so an oversized7// title priced the whole list out of the query cap: five proposals with 90 KB8// titles cost 3,172,507,361 gas against a 3,000,000,000 cap. Clamping the title9// before it is escaped brings the same five to 66,871,916.10//11// Runs in its own realm because it creates proposals, and the unit tests in the12// impl package assert hard-coded proposal ids against shared state.1314import (15 "strings"16 "testing"1718 "gno.land/r/gov/dao"19 "gno.land/r/gov/dao/impl/v0"20 "gno.land/r/gov/dao/memberstore/v0"21)2223const user address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"2425func init(cur realm) {26 memberstore.Get(0, cur).DeleteAll()27 memberstore.Get(0, cur).SetTier(memberstore.T1)28 memberstore.Get(0, cur).SetMember(memberstore.T1, user, memberstore.NewMember(3))29 dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(impl.NewGovDAO(), nil))30}3132func main(cur realm) {33 testing.SetOriginCaller(user)34 testing.SetRealm(testing.NewUserRealm(user))3536 short := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(37 "An ordinary title", "d", nil))38 long := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(39 strings.Repeat("t", 50000), "d", nil))4041 // An ordinary title is untouched. Real titles in examples/ are about 4042 // bytes, so the bound never reaches them.43 sout := dao.Render(cross(cur), short.String())44 println("an ordinary title is left alone:",45 strings.Contains(sout, "An ordinary title") && !strings.Contains(sout, "… truncated"))4647 // The proposal page cuts the title before escaping it. Asserting the marker48 // rather than a length: escaping first and cutting second would also49 // produce a short page, so length alone cannot tell the two apart.50 pout := dao.Render(cross(cur), long.String())51 println("the proposal page clamps a huge title:",52 strings.Contains(pout, "… truncated") && len(pout) < 4000)5354 // The list page escapes one title per proposal it shows, so it is the page55 // the bound actually protects.56 lout := dao.Render(cross(cur), "")57 println("the list page clamps it too:",58 strings.Contains(lout, "… truncated") && len(lout) < 4000)59}6061// Output:62// an ordinary title is left alone: true63// the proposal page clamps a huge title: true64// the list page clamps it too: true65AddMember(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.
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.