Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

admin_test.gno

20.64 Kb · 688 lines
  1package admin
  2
  3import (
  4	"chain/runtime"
  5	"strings"
  6	"testing"
  7
  8	"gno.land/p/akkadia/beta/accesscontrol"
  9	"gno.land/p/nt/uassert/v0"
 10)
 11
 12// ==================== Admin Tests ====================
 13
 14func TestTransferAdmin(cur realm, t *testing.T) {
 15	tests := []struct {
 16		name         string
 17		originCaller address
 18		realm        runtime.Realm
 19		newAdmin     address
 20		shouldPanic  bool
 21		panicMsg     string
 22	}{
 23		{"admin transfers", testAdmin, testing.NewUserRealm(testAdmin), testUser, false, ""},
 24		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testUser, true, "admin access required"},
 25		{"invalid address", testAdmin, testing.NewUserRealm(testAdmin), address(""), true, "invalid address"},
 26	}
 27
 28	for _, tt := range tests {
 29		setupCommonAdminTests(cur, t)
 30		testing.SetOriginCaller(tt.originCaller)
 31		testing.SetRealm(tt.realm)
 32
 33		if tt.shouldPanic {
 34			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
 35				TransferAdmin(cross(cur), tt.newAdmin)
 36			})
 37		} else {
 38			TransferAdmin(cross(cur), tt.newAdmin)
 39			uassert.Equal(t, testAdmin.String(), GetAdmin().String())
 40			uassert.Equal(t, tt.newAdmin.String(), GetPendingAdmin().String())
 41			uassert.True(t, IsAdmin(testAdmin))
 42			uassert.False(t, IsAdmin(tt.newAdmin))
 43		}
 44	}
 45}
 46
 47func TestAcceptAdmin(cur realm, t *testing.T) {
 48	tests := []struct {
 49		name         string
 50		setup        func()
 51		originCaller address
 52		realm        runtime.Realm
 53		shouldPanic  bool
 54		panicMsg     string
 55	}{
 56		{
 57			name: "pending admin accepts",
 58			setup: func() {
 59				testing.SetRealm(testing.NewUserRealm(testAdmin))
 60				TransferAdmin(cross(cur), testUser)
 61			},
 62			originCaller: testUser,
 63			realm:        testing.NewUserRealm(testUser),
 64		},
 65		{
 66			name: "unauthorized user cannot accept",
 67			setup: func() {
 68				testing.SetRealm(testing.NewUserRealm(testAdmin))
 69				TransferAdmin(cross(cur), testUser)
 70			},
 71			originCaller: unauthorizedUser,
 72			realm:        testing.NewUserRealm(unauthorizedUser),
 73			shouldPanic:  true,
 74			panicMsg:     "pending admin access required",
 75		},
 76		{
 77			name:         "missing pending admin",
 78			originCaller: testAdmin,
 79			realm:        testing.NewUserRealm(testAdmin),
 80			shouldPanic:  true,
 81			panicMsg:     "invalid pending admin address",
 82		},
 83	}
 84
 85	for _, tt := range tests {
 86		setupCommonAdminTests(cur, t)
 87		testing.SetOriginCaller(testAdmin)
 88		testing.SetRealm(testing.NewUserRealm(testAdmin))
 89
 90		if tt.setup != nil {
 91			tt.setup()
 92		}
 93
 94		testing.SetOriginCaller(tt.originCaller)
 95		testing.SetRealm(tt.realm)
 96
 97		if tt.shouldPanic {
 98			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
 99				AcceptAdmin(cross(cur))
100			})
101			continue
102		}
103
104		AcceptAdmin(cross(cur))
105		uassert.Equal(t, tt.originCaller.String(), GetAdmin().String())
106		uassert.Equal(t, "", GetPendingAdmin().String())
107	}
108}
109
110func TestTransferAdmin_RejectsPendingOverwrite(cur realm, t *testing.T) {
111	setupCommonAdminTests(cur, t)
112
113	testing.SetOriginCaller(testAdmin)
114	testing.SetRealm(testing.NewUserRealm(testAdmin))
115	TransferAdmin(cross(cur), testUser)
116	uassert.Equal(t, testUser.String(), GetPendingAdmin().String())
117
118	uassert.AbortsWithMessage(t, cur, "pending admin transfer already exists", func() {
119		TransferAdmin(cross(cur), testUser2)
120	})
121	uassert.Equal(t, testAdmin.String(), GetAdmin().String())
122	uassert.Equal(t, testUser.String(), GetPendingAdmin().String())
123}
124
125func TestTransferAdmin_AllowsOriginOnlyForEmptyBootstrapAdmin(cur realm, t *testing.T) {
126	setupCommonAdminTests(cur, t)
127	admin = address("")
128
129	testing.SetOriginCaller(address(""))
130	testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_bootstrap_relay"))
131	TransferAdmin(cross(cur), testUser)
132	uassert.Equal(t, "", GetAdmin().String())
133	uassert.Equal(t, testUser.String(), GetPendingAdmin().String())
134
135	testing.SetOriginCaller(testUser)
136	testing.SetRealm(testing.NewUserRealm(testUser))
137	AcceptAdmin(cross(cur))
138	uassert.Equal(t, testUser.String(), GetAdmin().String())
139	uassert.Equal(t, "", GetPendingAdmin().String())
140
141	testing.SetOriginCaller(testUser)
142	testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay_after_bootstrap"))
143	uassert.AbortsWithMessage(t, cur, "admin access required", func() {
144		TransferAdmin(cross(cur), testUser2)
145	})
146}
147
148func TestAdminInterrealmSecurity(cur realm, t *testing.T) {
149	tests := []struct {
150		name        string
151		setup       func(realm) realm
152		call        func(realm, realm)
153		shouldPanic bool
154		panicMsg    string
155		verify      func(t *testing.T)
156	}{
157		{
158			name: "accept admin rejects code realm caller",
159			setup: func(cur realm) realm {
160				testing.SetOriginCaller(testAdmin)
161				testing.SetRealm(testing.NewUserRealm(testAdmin))
162				TransferAdmin(cross(cur), testUser)
163				testing.SetOriginCaller(testUser)
164				testing.SetRealm(testing.NewCodeRealm("gno.land/r/admin/relay"))
165				return nil
166			},
167			call: func(cur realm, stale realm) {
168				AcceptAdmin(cross(cur))
169			},
170			panicMsg: "contract calls not allowed: function must be called directly by user",
171		},
172		{
173			name: "transfer admin rejects valid admin origin through code realm",
174			setup: func(cur realm) realm {
175				testing.SetOriginCaller(testAdmin)
176				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
177				return nil
178			},
179			call: func(cur realm, stale realm) {
180				TransferAdmin(cross(cur), testUser)
181			},
182			panicMsg: "admin access required",
183		},
184		{
185			name: "transfer admin rejects non-admin origin through code realm",
186			setup: func(cur realm) realm {
187				testing.SetOriginCaller(unauthorizedUser)
188				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
189				return nil
190			},
191			call: func(cur realm, stale realm) {
192				TransferAdmin(cross(cur), testUser)
193			},
194			panicMsg: "admin access required",
195		},
196		{
197			name: "cancel admin transfer",
198			setup: func(cur realm) realm {
199				testing.SetOriginCaller(testAdmin)
200				testing.SetRealm(testing.NewUserRealm(testAdmin))
201				TransferAdmin(cross(cur), testUser)
202				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
203				return nil
204			},
205			call: func(cur realm, stale realm) {
206				CancelAdminTransfer(cross(cur))
207			},
208			panicMsg: "admin access required",
209		},
210		{
211			name: "set explorer url",
212			setup: func(cur realm) realm {
213				testing.SetOriginCaller(testAdmin)
214				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
215				return nil
216			},
217			call: func(cur realm, stale realm) {
218				SetExplorerURL(cross(cur), "https://relay.akkadia.land")
219			},
220			panicMsg: "admin access required",
221		},
222		{
223			name: "set operator",
224			setup: func(cur realm) realm {
225				testing.SetOriginCaller(testAdmin)
226				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
227				return nil
228			},
229			call: func(cur realm, stale realm) {
230				SetOperator(cross(cur), testUser)
231			},
232			panicMsg: "admin access required",
233		},
234		{
235			name: "unset operator",
236			setup: func(cur realm) realm {
237				testing.SetOriginCaller(testAdmin)
238				testing.SetRealm(testing.NewUserRealm(testAdmin))
239				SetOperator(cross(cur), testUser)
240				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
241				return nil
242			},
243			call: func(cur realm, stale realm) {
244				UnsetOperator(cross(cur), testUser)
245			},
246			panicMsg: "admin access required",
247		},
248		{
249			name: "set fee collector",
250			setup: func(cur realm) realm {
251				testing.SetOriginCaller(testAdmin)
252				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
253				return nil
254			},
255			call: func(cur realm, stale realm) {
256				SetFeeCollector(cross(cur), testUser)
257			},
258			panicMsg: "admin access required",
259		},
260		{
261			name: "set protocol",
262			setup: func(cur realm) realm {
263				testing.SetOriginCaller(testAdmin)
264				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
265				return nil
266			},
267			call: func(cur realm, stale realm) {
268				SetProtocol(cross(cur), testProtocol)
269			},
270			panicMsg: "admin access required",
271		},
272		{
273			name: "set faucet target amount",
274			setup: func(cur realm) realm {
275				testing.SetOriginCaller(testAdmin)
276				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
277				return nil
278			},
279			call: func(cur realm, stale realm) {
280				SetFaucetTargetAmount(cross(cur), 1000000)
281			},
282			panicMsg: "admin access required",
283		},
284		{
285			name: "request faucet rejects operator origin through code realm",
286			setup: func(cur realm) realm {
287				testing.SetOriginCaller(testAdmin)
288				testing.SetRealm(testing.NewUserRealm(testAdmin))
289				SetOperator(cross(cur), testOperator)
290				SetFaucetTargetAmount(cross(cur), 1000000)
291				testing.SetOriginCaller(testOperator)
292				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_operator_faucet_relay"))
293				return nil
294			},
295			call: func(cur realm, stale realm) {
296				RequestFaucet(cross(cur))
297			},
298			panicMsg: "contract calls not allowed: function must be called directly by user",
299		},
300		{
301			name: "request faucet for",
302			setup: func(cur realm) realm {
303				testing.SetOriginCaller(testAdmin)
304				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
305				return nil
306			},
307			call: func(cur realm, stale realm) {
308				RequestFaucetFor(cross(cur), testOperator)
309			},
310			panicMsg: "admin access required",
311		},
312		{
313			name: "request faucets",
314			setup: func(cur realm) realm {
315				testing.SetOriginCaller(testAdmin)
316				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
317				return nil
318			},
319			call: func(cur realm, stale realm) {
320				RequestFaucets(cross(cur))
321			},
322			panicMsg: "admin access required",
323		},
324		{
325			name: "withdraw",
326			setup: func(cur realm) realm {
327				testing.SetOriginCaller(testAdmin)
328				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_relay"))
329				return nil
330			},
331			call: func(cur realm, stale realm) {
332				Withdraw(cross(cur), testUser, 1)
333			},
334			panicMsg: "admin access required",
335		},
336		{
337			name: "assert current realm rejects stale realm",
338			setup: func(cur realm) realm {
339				testing.SetOriginCaller(testAdmin)
340				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_stale_probe"))
341				return cur.Previous()
342			},
343			call: func(cur realm, stale realm) {
344				accesscontrol.AssertCurrentRealm(0, stale)
345			},
346			shouldPanic: true,
347			panicMsg:    "spoofed realm",
348		},
349		{
350			name: "assert admin rejects stale realm",
351			setup: func(cur realm) realm {
352				testing.SetOriginCaller(testAdmin)
353				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_stale_probe"))
354				return cur.Previous()
355			},
356			call: func(cur realm, stale realm) {
357				accesscontrol.AssertIsAdmin(0, stale, IsAdmin)
358			},
359			shouldPanic: true,
360			panicMsg:    "spoofed realm",
361		},
362		{
363			name: "pending admin caller rejects stale realm",
364			setup: func(cur realm) realm {
365				pendingAdmin = testUser
366				testing.SetOriginCaller(testAdmin)
367				testing.SetRealm(testing.NewCodeRealm("gno.land/r/akkadia/beta/admin_stale_probe"))
368				return cur.Previous()
369			},
370			call: func(cur realm, stale realm) {
371				mustGetPendingAdminUserCaller(0, stale)
372			},
373			shouldPanic: true,
374			panicMsg:    "spoofed realm",
375		},
376	}
377
378	for _, tt := range tests {
379		setupCommonAdminTests(cur, t)
380		stale := tt.setup(cur)
381		call := func() {
382			tt.call(cur, stale)
383		}
384		if tt.shouldPanic {
385			uassert.PanicsWithMessage(t, cur, tt.panicMsg, call)
386			continue
387		}
388		if tt.panicMsg != "" {
389			uassert.AbortsWithMessage(t, cur, tt.panicMsg, call)
390			continue
391		}
392		call()
393		if tt.verify != nil {
394			tt.verify(t)
395		}
396	}
397}
398
399func TestCancelAdminTransfer(cur realm, t *testing.T) {
400	tests := []struct {
401		name         string
402		setup        func()
403		originCaller address
404		realm        runtime.Realm
405		shouldPanic  bool
406		panicMsg     string
407	}{
408		{
409			name: "admin cancels pending transfer",
410			setup: func() {
411				testing.SetRealm(testing.NewUserRealm(testAdmin))
412				TransferAdmin(cross(cur), testUser)
413			},
414			originCaller: testAdmin,
415			realm:        testing.NewUserRealm(testAdmin),
416		},
417		{
418			name: "unauthorized user cannot cancel",
419			setup: func() {
420				testing.SetRealm(testing.NewUserRealm(testAdmin))
421				TransferAdmin(cross(cur), testUser)
422			},
423			originCaller: unauthorizedUser,
424			realm:        testing.NewUserRealm(unauthorizedUser),
425			shouldPanic:  true,
426			panicMsg:     "admin access required",
427		},
428		{
429			name:         "missing pending admin",
430			originCaller: testAdmin,
431			realm:        testing.NewUserRealm(testAdmin),
432			shouldPanic:  true,
433			panicMsg:     "invalid pending admin address",
434		},
435	}
436
437	for _, tt := range tests {
438		setupCommonAdminTests(cur, t)
439		testing.SetOriginCaller(testAdmin)
440		testing.SetRealm(testing.NewUserRealm(testAdmin))
441
442		if tt.setup != nil {
443			tt.setup()
444		}
445
446		testing.SetOriginCaller(tt.originCaller)
447		testing.SetRealm(tt.realm)
448
449		if tt.shouldPanic {
450			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
451				CancelAdminTransfer(cross(cur))
452			})
453			continue
454		}
455
456		CancelAdminTransfer(cross(cur))
457		uassert.Equal(t, testAdmin.String(), GetAdmin().String())
458		uassert.Equal(t, "", GetPendingAdmin().String())
459	}
460}
461
462func TestCancelAdminTransfer_PreservesAdmin(cur realm, t *testing.T) {
463	setupCommonAdminTests(cur, t)
464
465	testing.SetOriginCaller(testAdmin)
466	testing.SetRealm(testing.NewUserRealm(testAdmin))
467	TransferAdmin(cross(cur), testUser)
468
469	CancelAdminTransfer(cross(cur))
470	uassert.Equal(t, testAdmin.String(), GetAdmin().String())
471	uassert.True(t, IsAdmin(testAdmin))
472	uassert.Equal(t, "", GetPendingAdmin().String())
473}
474
475// ==================== ExplorerURL Tests ====================
476
477func TestSetExplorerURL(cur realm, t *testing.T) {
478	tests := []struct {
479		name         string
480		originCaller address
481		realm        runtime.Realm
482		url          string
483		shouldPanic  bool
484		panicMsg     string
485		expectedURL  string
486	}{
487		{"admin sets url", testAdmin, testing.NewUserRealm(testAdmin), "https://new.explorer.com", false, "", "https://new.explorer.com"},
488		{"trailing slash normalized", testAdmin, testing.NewUserRealm(testAdmin), "https://new.explorer.com///", false, "", "https://new.explorer.com"},
489		{"admin sets empty url", testAdmin, testing.NewUserRealm(testAdmin), "", true, "explorer URL is required", ""},
490		{"rejects http", testAdmin, testing.NewUserRealm(testAdmin), "http://new.explorer.com", true, "explorer URL must use https", ""},
491		{"rejects whitespace", testAdmin, testing.NewUserRealm(testAdmin), " https://new.explorer.com", true, "invalid explorer URL", ""},
492		{"rejects brackets", testAdmin, testing.NewUserRealm(testAdmin), "https://new.explorer.com/[test]", true, "invalid explorer URL", ""},
493		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), "https://hacker.com", true, "admin access required", ""},
494	}
495
496	for _, tt := range tests {
497		setupCommonAdminTests(cur, t)
498		testing.SetOriginCaller(tt.originCaller)
499		testing.SetRealm(tt.realm)
500
501		if tt.shouldPanic {
502			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
503				SetExplorerURL(cross(cur), tt.url)
504			})
505			uassert.Equal(t, "https://app.beta.akkadia.land", GetExplorerURL())
506		} else {
507			SetExplorerURL(cross(cur), tt.url)
508			uassert.Equal(t, tt.expectedURL, GetExplorerURL())
509		}
510	}
511}
512
513// ==================== Operator Tests ====================
514
515func TestSetOperator(cur realm, t *testing.T) {
516	tests := []struct {
517		name         string
518		originCaller address
519		realm        runtime.Realm
520		newAddr      address
521		shouldPanic  bool
522		panicMsg     string
523	}{
524		{"admin sets operator", testAdmin, testing.NewUserRealm(testAdmin), testUser, false, ""},
525		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testUser, true, "admin access required"},
526		{"invalid address", testAdmin, testing.NewUserRealm(testAdmin), address(""), true, "invalid address"},
527	}
528
529	for _, tt := range tests {
530		setupCommonAdminTests(cur, t)
531		testing.SetOriginCaller(tt.originCaller)
532		testing.SetRealm(tt.realm)
533
534		if tt.shouldPanic {
535			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
536				SetOperator(cross(cur), tt.newAddr)
537			})
538		} else {
539			SetOperator(cross(cur), tt.newAddr)
540			uassert.True(t, IsOperator(tt.newAddr))
541			uassert.True(t, IsOperator(testAdmin))
542		}
543	}
544}
545
546func TestGetOperators(cur realm, t *testing.T) {
547	setupCommonAdminTests(cur, t)
548
549	operators := GetOperators()
550	uassert.Equal(t, len(operators), 1)
551	uassert.Equal(t, operators[0].String(), testAdmin.String())
552
553	testing.SetRealm(testing.NewUserRealm(testAdmin))
554	SetOperator(cross(cur), testUser)
555
556	operators = GetOperators()
557	uassert.Equal(t, len(operators), 2)
558
559	operators[0] = unauthorizedUser
560	operatorsAgain := GetOperators()
561	uassert.Equal(t, len(operatorsAgain), 2)
562	uassert.False(t, containsOperator(operatorsAgain, unauthorizedUser))
563}
564
565func TestUnsetOperator(cur realm, t *testing.T) {
566	tests := []struct {
567		name         string
568		originCaller address
569		realm        runtime.Realm
570		addr         address
571		shouldPanic  bool
572		panicMsg     string
573	}{
574		{"admin unsets operator", testAdmin, testing.NewUserRealm(testAdmin), testUser, false, ""},
575		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testUser, true, "admin access required"},
576		{"invalid address", testAdmin, testing.NewUserRealm(testAdmin), address(""), true, "invalid address"},
577		{"not an operator", testAdmin, testing.NewUserRealm(testAdmin), unauthorizedUser, true, "address is not an operator"},
578	}
579
580	for _, tt := range tests {
581		setupCommonAdminTests(cur, t)
582		// Add testUser as operator for unset tests
583		testing.SetOriginCaller(testAdmin)
584		testing.SetRealm(testing.NewUserRealm(testAdmin))
585		SetOperator(cross(cur), testUser)
586
587		testing.SetOriginCaller(tt.originCaller)
588		testing.SetRealm(tt.realm)
589
590		if tt.shouldPanic {
591			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
592				UnsetOperator(cross(cur), tt.addr)
593			})
594		} else {
595			UnsetOperator(cross(cur), tt.addr)
596			uassert.False(t, IsOperator(tt.addr))
597			uassert.True(t, IsOperator(testAdmin))
598		}
599	}
600}
601
602// ==================== FeeCollector Tests ====================
603
604func TestSetFeeCollector(cur realm, t *testing.T) {
605	tests := []struct {
606		name         string
607		originCaller address
608		realm        runtime.Realm
609		newAddr      address
610		shouldPanic  bool
611		panicMsg     string
612	}{
613		{"admin sets feeCollector", testAdmin, testing.NewUserRealm(testAdmin), testUser, false, ""},
614		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testUser, true, "admin access required"},
615		{"invalid address", testAdmin, testing.NewUserRealm(testAdmin), address(""), true, "invalid address"},
616	}
617
618	for _, tt := range tests {
619		setupCommonAdminTests(cur, t)
620		testing.SetOriginCaller(tt.originCaller)
621		testing.SetRealm(tt.realm)
622
623		if tt.shouldPanic {
624			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
625				SetFeeCollector(cross(cur), tt.newAddr)
626			})
627			uassert.Equal(t, adminRealmAddr().String(), GetFeeCollector().String())
628		} else {
629			SetFeeCollector(cross(cur), tt.newAddr)
630			uassert.Equal(t, tt.newAddr.String(), GetFeeCollector().String())
631			uassert.True(t, IsFeeCollector(tt.newAddr))
632			uassert.False(t, IsFeeCollector(testAdmin))
633		}
634	}
635}
636
637// ==================== Protocol Tests ====================
638
639func TestSetProtocol(cur realm, t *testing.T) {
640	tests := []struct {
641		name         string
642		originCaller address
643		realm        runtime.Realm
644		newAddr      address
645		shouldPanic  bool
646		panicMsg     string
647	}{
648		{"admin sets protocol", testAdmin, testing.NewUserRealm(testAdmin), testUser, false, ""},
649		{"unauthorized", unauthorizedUser, testing.NewUserRealm(unauthorizedUser), testUser, true, "admin access required"},
650		{"invalid address", testAdmin, testing.NewUserRealm(testAdmin), address(""), true, "invalid address"},
651	}
652
653	for _, tt := range tests {
654		setupCommonAdminTests(cur, t)
655		testing.SetOriginCaller(tt.originCaller)
656		testing.SetRealm(tt.realm)
657
658		if tt.shouldPanic {
659			uassert.AbortsWithMessage(t, cur, tt.panicMsg, func() {
660				SetProtocol(cross(cur), tt.newAddr)
661			})
662			uassert.Equal(t, testAdmin.String(), GetProtocol().String())
663		} else {
664			SetProtocol(cross(cur), tt.newAddr)
665			uassert.Equal(t, tt.newAddr.String(), GetProtocol().String())
666			uassert.True(t, IsProtocol(tt.newAddr))
667			uassert.False(t, IsProtocol(testAdmin))
668		}
669	}
670}
671
672func TestRender(cur realm, t *testing.T) {
673	setupCommonAdminTests(cur, t)
674
675	testing.SetOriginCaller(testAdmin)
676	testing.SetRealm(testing.NewUserRealm(testAdmin))
677	SetOperator(cross(cur), testUser)
678	SetFeeCollector(cross(cur), testUser2)
679	SetProtocol(cross(cur), unauthorizedUser)
680	SetFaucetTargetAmount(cross(cur), 1000000)
681
682	output := Render("")
683	uassert.True(t, strings.Contains(output, testAdmin.String()), "render should include admin")
684	uassert.True(t, strings.Contains(output, testUser.String()), "render should include operator")
685	uassert.True(t, strings.Contains(output, testUser2.String()), "render should include fee collector")
686	uassert.True(t, strings.Contains(output, unauthorizedUser.String()), "render should include protocol")
687	uassert.True(t, strings.Contains(output, "1000000 ugnot"), "render should include faucet target")
688}