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

v0 source realm

untrusted-render: every path Render echoes was read off a crossing frame in Propose (cur.Previous().PkgPath(), which ...

Readme View source

gno.land/r/moul/x/upgrade/adminreg/facade/v0

The permanent facade of pattern F. Implementations nominate themselves from init (Propose); the owner promotes one by path string (Accept). Nothing serves until both have happened.

Accepting takes a string on purpose: an interface value cannot travel in a maketx call argument, so the original "admin hands the facade an object" shape was not reachable from a wallet at all.

See the pattern and the exploration.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/r/moul/x/upgrade/adminreg/facade/v0 dependency graph

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.

Overview

untrusted-render: every path Render echoes was read off a crossing frame in Propose (cur.Previous().PkgPath(), which a caller cannot forge or type), and Accept can only promote a key that is already in that tree.

Package facade is the permanent entry point of the "propose and accept" upgrade pattern (pattern F of the exploration; see ../../README.md).

Pattern E lets a deploy take the realm over on the spot. This one splits that into two steps that different people can hold: an implementation realm NOMINATES itself from its own init, and the owner ACCEPTS a package path in a separate transaction. Nothing serves until both have happened.

The split exists because of a mechanical limit, not just a governance preference. An implementation is an interface value, and a wallet cannot put one in a `maketx call` argument: only strings and numbers travel. The original shape of this pattern (the owner hands the facade an object) is therefore reachable only from `maketx run` or from another realm. Proposing from init and accepting by PATH makes both halves ordinary transactions.

Constants 1

const StageOpen, StageClosed, StageFrozen

1const (
2	StageOpen   = 0 // anything under the prefix may propose, the owner may accept any candidate
3	StageClosed = 1 // no new candidates; the owner may still accept among those already proposed
4	StageFrozen = 2 // nothing may be accepted again, whatever is live is final
5)
source

The stage ladder, copied in shape from Sui's UpgradeCap: compatible, additive, dependency-only, immutable, where a policy can only ever become MORE restrictive and make_immutable discards the cap. CosmWasm (a contract with no admin) and Solana (an upgrade authority set to None) reach the same place with one bit; the ladder is better because the interesting states are between "anything may take this over" and "nothing may ever change again".

This pattern has an owner and a candidate list, so it has a middle rung the owner-less selfreg cannot express: no new code, but still free to roll back among what is already deployed.

What the top rung does NOT do on its own: freezing this realm ends changes to the POINTER, not to the code behind it. A private implementation realm can be re-added at its own path, which would swap behaviour under a frozen facade. It holds here only because every implementation is public by construction: handing the facade its own object is exactly what forbids private (see ../../README.md).

Variables 1

Functions 11

func Accept

crossing Action
1func Accept(cur realm, pkgPath string)
source

Accept promotes a proposed path to live. Owner-gated, and it takes a STRING, so it is callable straight from a wallet.

func Candidates

Action
1func Candidates() []string
source

Candidates lists every path that has nominated itself, in order.

func Close

crossing Action
1func Close(cur realm)
source

Close stops new candidates. The owner may still accept among those already proposed, so a rollback stays possible while new code does not.

func Freeze

crossing Action
1func Freeze(cur realm)
source

Freeze ends this realm's upgradeability, forever. There is no rung above it and nothing takes it back: that is the whole point, and it is the only way out of every caller trusting the owner rather than the code.

func Greet

Action
1func Greet(name string) string
source

Greet forwards to the accepted implementation.

func Live

Action
1func Live() string
source

Live is the package path currently serving, or "" before the first Accept.

func Propose

crossing Action
1func Propose(cur realm, impl Impl)
source

Propose nominates the calling realm. Called from the implementation's init, so deploying makes a candidate and nothing more.

func Stage

Action
1func Stage() int
source

Stage is the rung this realm is on. It only ever goes up.

func Version

Action
1func Version() string
source

Version reports the accepted implementation's own version string.

Types 1

type Impl

interface
1type Impl interface {
2	Greet(name string) string
3	Version() string
4}
source

Impl is the contract an implementation realm must satisfy.

Imports 4

Source Files 5