Search Apps Documentation Source Content File Folder Download Copy Actions Download

admin.gno

3.30 Kb · 137 lines
  1package admin
  2
  3import (
  4	"chain"
  5	"chain/runtime/unsafe"
  6
  7	"gno.land/p/akkadia/v0/accesscontrol"
  8)
  9
 10const (
 11	TransferAdminEvent  = "TransferAdmin"
 12	AcceptAdminEvent    = "AcceptAdmin"
 13	CancelAdminEvent    = "CancelAdmin"
 14	SetExplorerURLEvent = "SetExplorerURL"
 15)
 16
 17var (
 18	admin        address
 19	pendingAdmin address
 20	explorerURL  string = "https://app.alpha.akkadia.land"
 21)
 22
 23func init() {
 24	caller := unsafe.OriginCaller()
 25	admin = caller
 26}
 27
 28func GetAdmin() address {
 29	return admin
 30}
 31
 32func GetPendingAdmin() address {
 33	return pendingAdmin
 34}
 35
 36func TransferAdmin(cur realm, newAdmin address) {
 37	assertNotFrozen()
 38	assertTransferAdminCaller(0, cur)
 39	assertValidAddress(newAdmin)
 40	if pendingAdmin.IsValid() {
 41		panic("pending admin transfer already exists")
 42	}
 43
 44	pendingAdmin = newAdmin
 45
 46	chain.Emit(
 47		TransferAdminEvent,
 48		"from", admin.String(),
 49		"to", newAdmin.String(),
 50	)
 51}
 52
 53func assertTransferAdminCaller(_ int, rlm realm) {
 54	if !admin.IsValid() {
 55		// The admin realm normally initializes admin from OriginCaller during
 56		// package deployment, so a live on-chain admin should be a valid address.
 57		// An empty admin is a bootstrap-only state observed by cross-package tests:
 58		// dependent realm tests can import admin before a real deploy signer exists,
 59		// leaving admin as address(""). In that state there is no valid user address
 60		// that can satisfy direct caller authorization, so requiring AssertIsAdmin
 61		// would make those tests unable to promote a real test admin at all.
 62		//
 63		// Keep the legacy OriginCaller check only for this invalid-admin bootstrap
 64		// state. This preserves the narrow test/bootstrap path where the current
 65		// placeholder admin is address(""), while ensuring that once a real admin is
 66		// accepted every subsequent admin transfer is direct-caller-only. In other
 67		// words, code-realm relays cannot borrow a valid admin signer's authority to
 68		// change pendingAdmin; the exception exists solely to escape the empty
 69		// imported-test initialization state.
 70		accesscontrol.AssertCurrentRealm(0, rlm)
 71		accesscontrol.AssertIsAdminOrigin(IsAdmin)
 72		return
 73	}
 74
 75	accesscontrol.AssertIsAdmin(0, rlm, IsAdmin)
 76}
 77
 78func AcceptAdmin(cur realm) {
 79	assertNotFrozen()
 80	if !pendingAdmin.IsValid() {
 81		panic("invalid pending admin address")
 82	}
 83	caller := mustGetPendingAdminUserCaller(0, cur)
 84
 85	prevAdmin := admin
 86	admin = caller
 87	pendingAdmin = address("")
 88
 89	chain.Emit(
 90		AcceptAdminEvent,
 91		"from", prevAdmin.String(),
 92		"to", admin.String(),
 93	)
 94}
 95
 96func CancelAdminTransfer(cur realm) {
 97	assertNotFrozen()
 98	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
 99	if !pendingAdmin.IsValid() {
100		panic("invalid pending admin address")
101	}
102
103	canceledAdmin := pendingAdmin
104	pendingAdmin = address("")
105
106	chain.Emit(
107		CancelAdminEvent,
108		"admin", admin.String(),
109		"pendingAdmin", canceledAdmin.String(),
110	)
111}
112
113func IsAdmin(address address) bool {
114	return address == admin
115}
116
117// SetExplorerURL sets the explorer base URL (admin only)
118func SetExplorerURL(cur realm, url string) {
119	assertNotFrozen()
120	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
121
122	normalizedURL := normalizeExplorerURL(url)
123	oldURL := explorerURL
124	explorerURL = normalizedURL
125
126	chain.Emit(
127		SetExplorerURLEvent,
128		"admin", admin.String(),
129		"oldURL", oldURL,
130		"newURL", normalizedURL,
131	)
132}
133
134// GetExplorerURL returns the explorer base URL
135func GetExplorerURL() string {
136	return explorerURL
137}