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.

z_contract_authority_shape_filetest.gno

3.59 Kb · 94 lines
 1// PKGPATH: gno.land/r/example
 2//
 3// Executes the contract-identity gate from a real realm.
 4//
 5// Two reasons this cannot be a plain unit test in p/moul/authz:
 6//
 7//  1. Example_* functions that take parameters and have no "// Output:"
 8//     are never run by `gno test` — a sentinel panic inside one still
 9//     reports ok. So the package's headline example, the shape readers
10//     copy, is invisible to CI unless something else runs it.
11//  2. The gate cannot be simulated from inside the package. The VM mints
12//     a crossing frame's realm from the CALLEE's declaring package, so a
13//     closure declared in p/moul/authz always presents that package's
14//     address no matter what testing.SetRealm says. Only a realm can
15//     present its own.
16//
17// (2) is the same mechanism as the capability leak, seen from the other
18// side: it is what makes `rlm.Address()` inside a crossing frame
19// unconditionally the realm's own address — and therefore what makes
20// `NewContractAuthority(ownPath)` + `DoByCurrent` a comparison of the
21// realm to itself that can never reject.
22//
23// WHAT THIS FILE PINS. Both halves go red if the identity gate is
24// reverted to its pre-fix `proposer: NewAutoAcceptAuthority()` default:
25//
26//   - a principal that is NOT the contract is refused;
27//   - the contract itself is accepted, so the gate does not lock out the
28//     legitimate driver.
29//
30// It deliberately does NOT demonstrate `DoByCurrent` on an own-path
31// authority. That pairing is the anti-pattern NewContractAuthority's
32// godoc forbids: it succeeds here and it would equally succeed for a
33// hostile caller, so asserting it green would document the hole as the
34// recommended shape. A filetest is confined to one realm and so cannot
35// exhibit the foreign caller itself; the package-level negatives
36// (TestForeignFrameCannotDriveContractAuthority,
37// TestContractPathIsolation) and r/gnops/valopers' filetests cover that.
38package example
39
40import (
41	"chain"
42
43	"gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/authz/v0"
44)
45
46var auth = authz.NewWithAuthority(
47	authz.NewContractAuthority(
48		"gno.land/r/example", // this realm's own path
49		func(_ string, action authz.PrivilegedAction) error { return action() },
50	),
51)
52
53var updated string
54
55// UpdateParams is the exported crossing entrypoint of the realm.
56//
57// DoByPrevious, not DoByCurrent: the principal is whoever crossed in, so
58// an unrelated realm calling this presents its own address and is
59// refused. Under DoByCurrent the principal would be this realm's own
60// address for every caller, and this entrypoint would be an
61// unauthenticated privileged write.
62//
63// Note what must NOT be added next to it: a function returning this
64// closure, or any other value carrying this frame. That is the leak.
65func UpdateParams(cur realm, v string) error {
66	return auth.DoByPrevious(0, cur, "update_params", func() error {
67		updated = v
68		return nil
69	})
70}
71
72func main(cur realm) {
73	// A principal that is not the contract is refused, and the action
74	// does not run. This is the assertion the pre-fix AutoAccept default
75	// could not make.
76	outsider := chain.PackageAddress("gno.land/r/outsider")
77	err := auth.Authority().Authorize(outsider, "update_params", func() error {
78		updated = "SHOULD-NOT-LAND"
79		return nil
80	})
81	println("outsider err:", err)
82	println("updated:", updated)
83
84	// The contract itself is accepted: main and UpdateParams are both in
85	// gno.land/r/example, so cur.Previous() is this realm.
86	println("contract err:", UpdateParams(cross(cur), "governed-value"))
87	println("updated:", updated)
88}
89
90// Output:
91// outsider err: unauthorized
92// updated:
93// contract err: undefined
94// updated: governed-value