1package authz23// Example_basic demonstrates initializing and using a basic member authority4func Example_basic(cur realm) {5 // Initialize from the EOA caller (e.g. in init(cur realm) of a realm6 // being deployed): caller passes the EOA address; the realm itself7 // is responsible for verifying the caller is an EOA when needed.8 auth := NewWithMembers(cur.Previous().Address())910 // Authorize with DoByPrevious, NOT DoByCurrent: the member set holds11 // cur.Previous().Address(), and DoByCurrent would present12 // cur.Address() -- this realm -- which is never in that set, so the13 // action would silently never run. Seeding and authorizing must read14 // the SAME side of the frame. Matches the package Quick Start.15 if err := auth.DoByPrevious(0, cur, "update_config", func() error {16 // config = newValue17 return nil18 }); err != nil {19 panic(err)20 }21}2223// Example_addingMembers demonstrates how to add new members to a member authority24func Example_addingMembers(cur realm) {25 // Seed with Previous(), not Address(): MemberAuthority.AddMember26 // derives its principal as rlm.Previous().Address(), so a set holding27 // only cur.Address() authorizes nobody and the AddMember below fails.28 auth := NewWithMembers(cur.Previous().Address())2930 // Add a new member to the authority31 memberAuth := auth.Authority().(*MemberAuthority)32 if err := memberAuth.AddMember(0, cur, address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")); err != nil {33 panic(err)34 }35}3637// Example_contractAuthority demonstrates a contract-based authority.38//39// A plain NewContractAuthority accepts exactly one principal:40// chain.PackageAddress(path). Point `path` at the principal you want to41// ASSERT -- normally the governance realm that will drive the action --42// and authorize with DoByPrevious, so the comparison is against whoever43// crossed in. See NewContractAuthority's godoc.44//45// Do NOT pair a plain ContractAuthority on your OWN path with46// DoByCurrent. rlm.Address() inside any crossing frame of a realm is47// unconditionally PackageAddress(ownPath), so that gate compares the48// realm to itself, can never reject, and any exported crossing49// entrypoint next to it becomes an unauthenticated privileged write --50// the self-comparing-gate shape. Own-path is right only when something51// OTHER than your own frame supplies the caller, i.e. DoByPrevious from52// a realm you deliberately let call in, or Transfer.53//54// Nothing here catches a wrong pairing: Example_* functions that take55// any parameter are never executed by `gno test` (see isExampleFunc in56// gnovm/pkg/test/test.go -- it rejects on method receiver, parameters or57// results; "// Output:" plays no part in the predicate, so adding one58// does NOT make the body run), so a sentinel panic in here still reports59// ok. filetests/z_contract_authority_shape_filetest.gno executes the60// gate from a real realm instead.61//62// Corollary of the identity gate: do not export anything that returns a63// crossing closure of this realm, or callers inherit the authority.64func Example_contractAuthority(cur realm) {65 // This realm asserts "the governance realm governs me".66 auth := NewWithAuthority(67 NewContractAuthority(68 "gno.land/r/gov/dao", // the principal asserted, not this realm69 mockDAOHandler, // defined elsewhere for example70 ),71 )7273 // Authorized only when gno.land/r/gov/dao is the realm that crossed74 // into this function -- in practice, when a passed proposal executes.75 // Every other caller presents its own address here and is refused,76 // which is the whole point of the gate. Never discard this error.77 if err := auth.DoByPrevious(0, cur, "update_params", func() error {78 return nil79 }); err != nil {80 panic(err)81 }82}8384// Example_restrictedContractAuthority demonstrates a contract authority with member-only proposals85func Example_restrictedContractAuthority(cur realm) {86 // Initialize member authority for proposers87 proposerAuth := NewMemberAuthority(88 address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"), // admin189 address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"), // admin290 )9192 // Create contract authority with restricted proposers93 auth := NewWithAuthority(94 NewRestrictedContractAuthority(95 "gno.land/r/demo/dao",96 mockDAOHandler,97 proposerAuth,98 ),99 )100101 // Only members can propose, and contract must approve.102 //103 // DoByPrevious, not DoByCurrent: the proposer set holds EOA104 // addresses, and DoByCurrent would present this realm's own address,105 // which is in no member set -- the proposer would reject and the106 // action would silently never run.107 if err := auth.DoByPrevious(0, cur, "update_params", func() error {108 // Executes after:109 // 1. Proposer initiates110 // 2. DAO approves111 return nil112 }); err != nil {113 panic(err)114 }115}116117// Example_switchingAuthority demonstrates switching from member to contract118// authority.119//120// Note what a plain ContractAuthority on a FOREIGN path means after the121// transfer: this realm loses the ability to take the authority back, and122// DoByCurrent against it is dead. It is NOT a one-way door in the123// stronger sense an earlier draft implied — the foreign realm can still124// drive and rotate it via Previous() once it crosses in, which is the125// intended async-DAO shape. What is given up is the original owner's126// claim, not the authority's mutability. (The ADR for this change states127// the same thing; keep the two in step.) To keep the authority here128// while letting others propose, transfer to129// NewRestrictedContractAuthority(ownPath, handler, proposerAuth)130// instead.131func Example_switchingAuthority(cur realm) {132 // Start with member authority.133 //134 // Seed the member set with Previous(), not Address(): Transfer135 // derives its principal as rlm.Previous().Address(), so a set136 // containing only cur.Address() authorizes nobody but a137 // same-package cross-call, and the Transfer below would abort for138 // every external caller — including a realm that copies this into139 // init(cur realm), which then fails its deploy tx. Matches140 // Example_basic and NewWithMembers' godoc.141 auth := NewWithMembers(cur.Previous().Address())142143 // Create and switch to contract authority — control moves to144 // gno.land/r/demo/dao.145 daoAuthority := NewContractAuthority(146 "gno.land/r/demo/dao",147 mockDAOHandler,148 )149 if err := auth.Transfer(0, cur, daoAuthority); err != nil {150 panic(err)151 }152}153154// Mock handler for examples155func mockDAOHandler(title string, action PrivilegedAction) error {156 return action()157}158Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.