← Back to Realms

Realm

gno.land/r/gov/dao

Overview

Realm Path
gno.land/r/gov/dao
Exported Functions
21
State Entries
19
Source Files
5
Total Package Entries
41

Exported Functions

21 exported functions

State

19 state entries

Source Code

FILES
allowlist_test.gno
go
1package dao
2
3import (
4	"testing"
5
6	"gno.land/p/nt/uassert/v0"
7	"gno.land/p/nt/urequire/v0"
8)
9
10// allowedDAOs is the sole authorization for UpdateImpl, memberstore.Get,
11// treasury.Send and treasury.SetTokenKeys, and InAllowedDAOs() fails OPEN when
12// it is empty — the bootstrap window that lets the genesis MsgRun seed the
13// member set before lockdown.
14//
15// These tests pin that the transition empty -> non-empty is one-way: once the
16// DAO is locked down, UpdateImpl cannot put it back into the fail-open state.
17// Both paths below reopened the gate before the guard, because
18// NewUpdateRequest copies nil into a NON-nil empty slice and the old test was
19// `r.AllowedDAOs != nil`.
20//
21// These call the real UpdateImpl through a code realm rather than replaying
22// its logic, so reverting the guard makes them fail.
23func TestUpdateImplIgnoresEmptyAllowedDAOs(cur realm, t *testing.T) {
24	savedDAOs, savedDAO := allowedDAOs, dao
25	defer func() { allowedDAOs, dao = savedDAOs, savedDAO }()
26
27	lock := func() {
28		allowedDAOs = nil // reopen so the next UpdateImpl is permitted
29		testing.SetRealm(testing.NewCodeRealm(v0))
30		UpdateImpl(cross(cur), UpdateRequest{DAO: &dummyDao{}, AllowedDAOs: []string{v0}})
31		uassert.False(t, InAllowedDAOs(invalid), "precondition: locked down")
32	}
33
34	// Path 1: NewUpdateRequest(d, nil) — "swap the implementation, leave
35	// permissions alone", and the form v0/loader uses.
36	lock()
37	testing.SetRealm(testing.NewCodeRealm(v0))
38	UpdateImpl(cross(cur), NewUpdateRequest(&dummyDao{}, nil))
39	uassert.False(t, InAllowedDAOs(invalid),
40		"a nil AllowedDAOs must not reopen the permission gate")
41
42	// Path 2: an explicitly empty slice via the struct literal.
43	lock()
44	testing.SetRealm(testing.NewCodeRealm(v0))
45	UpdateImpl(cross(cur), UpdateRequest{DAO: &dummyDao{}, AllowedDAOs: []string{}})
46	uassert.False(t, InAllowedDAOs(invalid),
47		"an empty AllowedDAOs must not reopen the permission gate")
48
49	// A legitimate extension of the list must still apply.
50	lock()
51	testing.SetRealm(testing.NewCodeRealm(v0))
52	UpdateImpl(cross(cur), NewUpdateRequest(&dummyDao{}, []string{v0, v1}))
53	uassert.True(t, InAllowedDAOs(v1), "a non-empty AllowedDAOs must still be stored")
54	uassert.False(t, InAllowedDAOs(invalid), "and must not admit anyone else")
55}
56
57// The bootstrap window itself must survive the guard: with no allowlist
58// configured yet, any caller is allowed so the genesis MsgRun can seed the
59// member set and then lock down.
60func TestBootstrapWindowStillOpen(t *testing.T) {
61	saved := allowedDAOs
62	defer func() { allowedDAOs = saved }()
63
64	allowedDAOs = nil
65	uassert.True(t, InAllowedDAOs("gno.land/r/gov/dao/loader/v0"),
66		"an unset allowlist must stay open for genesis bootstrap")
67}
68
69// len(AllowedDAOs) != 0 is not sufficient on its own. InAllowedDAOs compares by
70// exact string and a user realm's PkgPath() is "", so a single "" entry admits
71// any caller whose previous frame is a user realm — the same fail-open outcome
72// the guard exists to prevent. NewUpgradeDaoImplRequest passes its realmPkg
73// argument straight into the list, so an empty one reaches here.
74func TestUpdateImplRejectsBlankAllowedDAOEntry(cur realm, t *testing.T) {
75	savedDAOs, savedDAO := allowedDAOs, dao
76	defer func() { allowedDAOs, dao = savedDAOs, savedDAO }()
77
78	for _, blank := range []string{"", "   "} {
79		allowedDAOs = nil
80		testing.SetRealm(testing.NewCodeRealm(v0))
81		UpdateImpl(cross(cur), UpdateRequest{DAO: &dummyDao{}, AllowedDAOs: []string{v0}})
82
83		testing.SetRealm(testing.NewCodeRealm(v0))
84		urequire.AbortsWithMessage(t, cur,
85			"AllowedDAOs entries must be realm paths; got an empty one",
86			func() {
87				UpdateImpl(cross(cur), UpdateRequest{
88					DAO:         &dummyDao{},
89					AllowedDAOs: []string{v0, blank},
90				})
91			})
92
93		uassert.False(t, InAllowedDAOs(""),
94			"a blank entry must never make it into the allowlist")
95		uassert.True(t, InAllowedDAOs(v0),
96			"the rejected request must leave the previous allowlist intact")
97	}
98}
99
100// A padded entry passes a plain non-blank test but is useless: entries are
101// stored exactly as given and InAllowedDAOs compares whole strings, so
102// " gno.land/r/x " matches no caller. The list is still non-empty, so the
103// bootstrap window is closed. A proposal that padded every entry would lock
104// the DAO out of its own allowlist with no way back.
105func TestUpdateImplRejectsPaddedAllowedDAOEntry(cur realm, t *testing.T) {
106	savedDAOs, savedDAO := allowedDAOs, dao
107	defer func() { allowedDAOs, dao = savedDAOs, savedDAO }()
108
109	for _, padded := range []string{" " + v1, v1 + " ", "\t" + v1} {
110		allowedDAOs = nil
111		testing.SetRealm(testing.NewCodeRealm(v0))
112		UpdateImpl(cross(cur), UpdateRequest{DAO: &dummyDao{}, AllowedDAOs: []string{v0}})
113
114		testing.SetRealm(testing.NewCodeRealm(v0))
115		urequire.AbortsWithMessage(t, cur,
116			"AllowedDAOs entries must not have leading or trailing spaces; entry 1",
117			func() {
118				UpdateImpl(cross(cur), UpdateRequest{
119					DAO:         &dummyDao{},
120					AllowedDAOs: []string{v0, padded},
121				})
122			})
123
124		uassert.False(t, InAllowedDAOs(padded),
125			"a padded entry must never make it into the allowlist")
126		uassert.True(t, InAllowedDAOs(v0),
127			"the rejected request must leave the previous allowlist intact")
128	}
129}
130

Raw Package Data

Raw JSON data