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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

config.gno

4.21 Kb · 115 lines
  1// Package config is the one realm moul's other realms read their settings
  2// from: a key/value store plus the manager list that decides who may write it.
  3//
  4// # Why a realm and not a constant
  5//
  6// A value shared by several contracts, hardcoded in each, is changed by
  7// redeploying each. On mainnet a public realm cannot even be redeployed at its
  8// own path, so "changing it" means a new version and a new path for every
  9// consumer. Here it is a transaction.
 10//
 11// # Bump rarely, and never for a new setting
 12//
 13// This realm IS public and versioned, so its path moves on every bump. That
 14// makes a bump expensive, which is exactly why the settings API is generic: a
 15// new setting is a new KEY, and a key costs one transaction. Only a change to
 16// the shape of this realm (a new function, a changed signature) is worth a
 17// version.
 18//
 19// # When a bump does happen, the state does not move
 20//
 21// A later version imports this one and relays to it rather than holding
 22// anything of its own, so v1, v2 and v3 all read and write the same settings,
 23// the same pause and the same member list. Delegation only runs backwards in
 24// time, which is why the root is the oldest version that has the state and not
 25// the newest. See proxy.gno.
 26//
 27// # What lives here
 28//
 29// settings.gno  the key/value store, and the mygnoscan accessors over it
 30// keys.gno      the key grammar: a name, optionally scoped to one realm
 31// blocks.gno    the notice a realm renders above and below its content
 32// pause.gno     the switch a realm checks before it acts
 33// proxy.gno     the relay that lets a later version share this state
 34// config.gno    the member list, unchanged from v0
 35//
 36// # Governance
 37//
 38// init seeds the authority with the deploying EOA. Everything that writes goes
 39// through Authorizer, so transferring authority to a DAO transfers the
 40// settings with it: there is no address hardcoded on the write path.
 41package config
 42
 43import (
 44	"errors"
 45
 46	"gno.land/p/nym-moultest123/authz/v0"
 47)
 48
 49var Authorizer *authz.Authorizer
 50
 51func init(cur realm) {
 52	if !cur.Previous().IsUserCall() {
 53		panic("r/moul/config must be initialized by an EOA")
 54	}
 55	Authorizer = authz.NewWithMembers(cur.Previous().Address())
 56}
 57
 58// AddManager adds a new address to the list of authorized managers.
 59// This only works if the current authority is a MemberAuthority.
 60// The caller must be authorized by the current authority.
 61func AddManager(cur realm, addr address) error {
 62	memberAuth, ok := Authorizer.Authority().(*authz.MemberAuthority)
 63	if !ok {
 64		return errors.New("current authority is not a MemberAuthority, cannot add manager directly")
 65	}
 66	return memberAuth.AddMember(0, cur, addr)
 67}
 68
 69// RemoveManager removes an address from the list of authorized managers.
 70// This only works if the current authority is a MemberAuthority.
 71// The caller must be authorized by the current authority.
 72func RemoveManager(cur realm, addr address) error {
 73	memberAuth, ok := Authorizer.Authority().(*authz.MemberAuthority)
 74	if !ok {
 75		return errors.New("current authority is not a MemberAuthority, cannot remove manager directly")
 76	}
 77	return memberAuth.RemoveMember(0, cur, addr)
 78}
 79
 80// TransferManagement transfers the authority to manage keys to a new authority.
 81// The caller must be authorized by the current authority.
 82func TransferManagement(cur realm, newAuthority authz.Authority) error {
 83	if newAuthority == nil {
 84		return errors.New("new authority cannot be nil")
 85	}
 86	return Authorizer.Transfer(0, cur, newAuthority)
 87}
 88
 89// ListManagers returns a slice of all managed keys.
 90func ListManagers(cur realm) []address {
 91	var keyList []address
 92	memberAuth, ok := Authorizer.Authority().(*authz.MemberAuthority)
 93	if !ok {
 94		return keyList
 95	}
 96	tree := memberAuth.Tree()
 97	if !ok || tree == nil {
 98		return keyList // Return empty list if tree is not as expected or nil
 99	}
100	tree.Iterate("", "", func(key string, _ any) bool {
101		keyList = append(keyList, address(key))
102		return false
103	})
104	return keyList
105}
106
107func HasManager(cur realm, addr address) bool {
108	memberAuth, ok := Authorizer.Authority().(*authz.MemberAuthority)
109	if !ok {
110		return false // Return false if not a MemberAuthority or doesn't exist
111	}
112	// Use the MemberAuthority's specific RemoveMember method,
113	// which internally performs the authorization check.
114	return memberAuth.Has(addr)
115}