PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/vesting

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
vesting
Namespace
g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr
Files
2 (gnomod.toml)
Exported functions
13
Module
gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/vesting
gno
0.9

Files (2)

  • gnomod.tomltoml
  • vesting.gnogno
vesting.gnogno
1// Package vesting holds grants of GNOT, BUBBLE or any registered GRC20 and pays each out on its own schedule:2// a share at the start, the rest by the day over a term, to one beneficiary, for as long as the grant's owner3// does not revoke it. Anyone may open a grant for anyone; nothing here is a setting but each grant's owner.4//5// Every grant has its OWN address — the realm's sub-realm `grant-<id>` (chain.DerivePkgSubAddr) — and that is how6// it is funded: send the tokens there (a bank send for GNOT, Transfer for a GRC20, a holders' vote that mints7// BUBBLE to it). The realm moves tokens out of a grant's address and never between grants; what sits at the8// realm's main address belongs to nobody and stays there, so send only to a grant's address.9//10// The schedule. Nothing before start, or before start + cliff; at start the up-front share is vested; each full11// day after start vests an equal share of the rest, until day Days, when all of Total has vested (Days 0: all of12// it at start). Claim pays the beneficiary what has vested and not yet been paid, as far as the grant's balance13// goes; anyone may call it, since the money has one destination. Revoke, by the owner, freezes the schedule where14// it stands and returns everything above what has vested to the owner; what had vested stays the beneficiary's to15// claim. A revoke before the up-front share has arrived (what was already paid counts as arrived) VOIDS the grant:16// nothing vests, and whatever lands later is the owner's to sweep. Sweep, by the owner, returns what the schedule can never owe (a gift,17// a double funding) without ending anything. A grant opened with no owner is irrevocable, and its excess is the18// beneficiary's to sweep.19//20// Votes. BUBBLE held by a grant is self-delegated, inside the token's ledger, to the grant's own address, and this21// realm never delegates it or votes with it; the beneficiary's weight grows as they claim.22//23// Immutable, not private (gnomod.toml).24package vesting2526import (27	"chain"28	"chain/banker"29	"strconv"30	"strings"31	"time"3233	"gno.land/p/nt/avl/v0"34	"gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/bubble"35	"gno.land/r/nt/grc20reg/v0"36)3738const (39	pkgPath = "gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/vesting" // must match gnomod.toml40	day     = int64(86400)4142	// GNOT and BUBBLE are the two tokens named directly; every other token is a registry key43	// (gno.land/r/nt/grc20reg/v0) such as gno.land/r/g1leu8d2…95wr/wbubble.BUBBLE.44	GNOT   = "ugnot"45	BUBBLE = "gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/bubble"4647	MaxDays = int64(36500) // a term, and a cliff, of at most a hundred years: the arithmetic below counts on it48	maxNote = 12049	listMax = 50 // grants the front page lists50)5152type kind int5354const (55	kindNative kind = iota56	kindBubble57	kindRegistry58)5960// Grant is one schedule. The fields are read through Get; only this realm writes them.61type Grant struct {62	ID          int6463	Token       string  // GNOT, BUBBLE or a registry key64	Creator     address // who opened it (named on the page: an owner is named, not implied to have opened it)65	Owner       address // may revoke and sweep; "" for an irrevocable grant66	OwnerNext   address // named by the owner, taken by the named: the two-step hand-off67	Beneficiary address68	Total       int64 // base units69	Upfront     int64 // vested at start70	Start       int64 // unix time the schedule counts from71	CliffDays   int64 // nothing is claimable before Start + CliffDays72	Days        int64 // the rest vests by the day over this many days after Start73	Claimed     int64 // paid to the beneficiary74	Returned    int64 // sent back to the owner75	RevokedAt   int64 // 0 while the grant runs76	Voided      bool  // revoked before anything arrived or was paid: nothing vests77	Note        string78}7980var (81	grants = avl.NewTree() // key(id) → *Grant82	last   int6483)8485// init refuses a deploy at a path other than pkgPath: Address() would then name sub-addresses nothing controls.86func init(cur realm) {87	if cur.Address() != chain.PackageAddress(pkgPath) {88		panic("vesting: deployed at a path other than pkgPath")89	}90}9192// ---------------------------------------------------------------- reading --9394func Count() int64 { return last }9596// Get is a copy of the grant.97func Get(id int64) Grant { return *get(id) }9899// Address is where a grant is funded: the realm's sub-realm for it. Only for a grant that exists.100func Address(id int64) address {101	get(id)102	return chain.DerivePkgSubAddr(pkgPath, subpath(id))103}104105// Balance is what the grant's address holds of its token.106func Balance(id int64) int64 { return balance(get(id)) }107108// Vested is what the schedule has released by now — or by the revoke, if there was one. Never above Total.109func Vested(id int64) int64 { return vested(get(id)) }110111// Claimable is what Claim would pay now: the vested part not yet paid, as far as the balance goes.112func Claimable(id int64) int64 { return claimable(get(id)) }113114func subpath(id int64) string { return "grant-" + strconv.FormatInt(id, 10) }115116func key(id int64) string {117	s := strconv.FormatInt(id, 10)118	for len(s) < 12 {119		s = "0" + s120	}121	return s122}123124func get(id int64) *Grant {125	if id <= 0 || id > last {126		panic("vesting: no grant " + strconv.FormatInt(id, 10))127	}128	return grants.Get(key(id)).(*Grant)129}130131func balance(g *Grant) int64 {132	addr := chain.DerivePkgSubAddr(pkgPath, subpath(g.ID))133	switch kindOf(g.Token) {134	case kindNative:135		return banker.NewReadonlyBanker().GetCoin(addr, GNOT) // one denom read: dust in other denoms cannot bloat it136	case kindBubble:137		return bubble.BalanceOf(addr)138	}139	return grc20reg.MustGet(g.Token).BalanceOf(addr)140}141142func vested(g *Grant) int64 {143	if g.Voided {144		return 0145	}146	t := time.Now().Unix()147	if g.RevokedAt != 0 {148		t = g.RevokedAt149	}150	return vestedAt(g, t)151}152153// vestedAt is the schedule itself. The split of rest*d/Days into a quotient and a remainder part keeps every154// intermediate inside int64 for any Total and a term under MaxDays, and equals the exact floor.155func vestedAt(g *Grant, t int64) int64 {156	if t < g.Start || t < g.Start+g.CliffDays*day {157		return 0158	}159	d := (t - g.Start) / day160	if g.Days == 0 || d >= g.Days {161		return g.Total162	}163	rest := g.Total - g.Upfront164	return g.Upfront + (rest/g.Days)*d + (rest%g.Days)*d/g.Days165}166167func claimable(g *Grant) int64 {168	due := vested(g) - g.Claimed169	if bal := balance(g); due > bal {170		due = bal171	}172	if due < 0 {173		return 0174	}175	return due176}177178func kindOf(token string) kind {179	switch token {180	case GNOT:181		return kindNative182	case BUBBLE:183		return kindBubble184	}185	return kindRegistry186}187188// canon names the token as the realm stores it: GNOT and BUBBLE by their constants, anything else by its registry189// key, which must resolve.190func canon(token string) string {191	switch strings.ToLower(token) {192	case "gnot", "ugnot":193		return GNOT194	case "bubble", BUBBLE:195		return BUBBLE196	}197	if grc20reg.Get(token) == nil {198		panic("vesting: unknown token " + token + ": say gnot, bubble, or a key of gno.land/r/nt/grc20reg/v0")199	}200	return token201}202203// ---------------------------------------------------------------- writing --204205func caller(cur realm) address {206	if !cur.IsCurrent() {207		panic("vesting: spoofed realm")208	}209	return cur.Previous().Address()210}211212func mustBeOwner(cur realm, g *Grant) {213	if g.Owner == "" {214		panic("vesting: this grant has no owner; it cannot be revoked or handed on")215	}216	if caller(cur) != g.Owner {217		panic("vesting: only the grant's owner")218	}219}220221// Create opens a grant and returns its id. owner may revoke it ("" makes it irrevocable); the tokens are sent to222// Address(id) afterwards, by anyone. token: "gnot", "bubble" or a registry key. start 0 is now; a past start is223// allowed, a future one up to a hundred years out. days 0 vests everything at start. note is a label of up to 120224// plain characters (no markup: the pages render it).225func Create(cur realm, owner, beneficiary address, token string, total, upfront, start, cliffDays, days int64, note string) int64 {226	creator := caller(cur)227	if !beneficiary.IsValid() {228		panic("vesting: the beneficiary is not an address")229	}230	if owner != "" && !owner.IsValid() {231		panic("vesting: the owner is not an address")232	}233	if owner == beneficiary {234		panic("vesting: the owner cannot be the beneficiary")235	}236	if total <= 0 {237		panic("vesting: the total must be positive")238	}239	if upfront < 0 || upfront > total {240		panic("vesting: the up-front share is between 0 and the total")241	}242	if days < 0 || days > MaxDays || cliffDays < 0 || cliffDays > MaxDays {243		panic("vesting: days and cliffDays are between 0 and " + strconv.FormatInt(MaxDays, 10))244	}245	now := time.Now().Unix()246	if start < 0 || start > now+MaxDays*day {247		panic("vesting: start is a unix time within a hundred years, or 0 for now")248	}249	if start == 0 {250		start = now251	}252	if next := chain.DerivePkgSubAddr(pkgPath, subpath(last+1)); beneficiary == next || owner == next {253		panic("vesting: a grant cannot pay its own address")254	}255	if len(note) > maxNote {256		panic("vesting: the note is at most " + strconv.Itoa(maxNote) + " characters")257	}258	for i := 0; i < len(note); i++ {259		if note[i] < 0x20 || note[i] == 0x7f || strings.IndexByte("[]()<>`*_#|\\", note[i]) >= 0 {260			panic("vesting: the note is plain text without markup")261		}262	}263	token = canon(token)264	last++265	g := &Grant{ID: last, Token: token, Creator: creator, Owner: owner, Beneficiary: beneficiary, Total: total, Upfront: upfront, Start: start, CliffDays: cliffDays, Days: days, Note: note}266	grants.Set(key(last), g)267	chain.Emit("Grant", "id", strconv.FormatInt(last, 10), "token", token, "to", beneficiary.String(), "owner", owner.String(), "by", creator.String(), "total", strconv.FormatInt(total, 10), "address", Address(last).String())268	return last269}270271// Claim pays the beneficiary everything claimable and returns the amount. Anyone may call it.272func Claim(cur realm, id int64) int64 {273	caller(cur)274	g := get(id)275	n := claimable(g)276	if n <= 0 {277		if vested(g) > g.Claimed {278			panic("vesting: nothing here to pay yet; the grant's address holds less than is due")279		}280		panic("vesting: nothing to claim")281	}282	g.Claimed += n283	send(cur, g, g.Beneficiary, n)284	chain.Emit("Claim", "id", strconv.FormatInt(id, 10), "to", g.Beneficiary.String(), "amount", strconv.FormatInt(n, 10))285	return n286}287288// Revoke ends the schedule where it stands (the first time) and returns to the owner everything the grant holds289// beyond what has vested and is still the beneficiary's to claim. Before the up-front share has arrived, counting290// what was already paid out as arrived, it voids the grant instead: nothing vests, ever — so a unit of dust sent291// ahead of the owner's revoke, claimed or not, cannot turn a void into a freeze that keeps the up-front share. (A292// grant with no up-front share measures against what the schedule had released by the revoke.) Returns what went293// back; 0 when nothing did.294func Revoke(cur realm, id int64) int64 {295	g := get(id)296	mustBeOwner(cur, g)297	if g.RevokedAt == 0 {298		g.RevokedAt = time.Now().Unix()299		floor := g.Upfront300		if floor == 0 {301			floor = vestedAt(g, g.RevokedAt)302		}303		if floor == 0 {304			floor = 1305		}306		g.Voided = g.Claimed+balance(g) < floor307		chain.Emit("Revoked", "id", strconv.FormatInt(id, 10), "at", strconv.FormatInt(g.RevokedAt, 10), "voided", strconv.FormatBool(g.Voided))308	}309	return sweep(cur, g)310}311312// Sweep returns to the owner what the schedule can never owe the beneficiary — above the unpaid rest of the grant313// while it runs, above what is still claimable once revoked — without ending anything. Owner only; on a grant with314// no owner the excess is the beneficiary's, and anyone may send it there.315func Sweep(cur realm, id int64) int64 {316	g := get(id)317	if g.Owner == "" {318		caller(cur)319		return sweepTo(cur, g, g.Beneficiary)320	}321	mustBeOwner(cur, g)322	return sweep(cur, g)323}324325func sweep(cur realm, g *Grant) int64 { return sweepTo(cur, g, g.Owner) }326327func sweepTo(cur realm, g *Grant, to address) int64 {328	owed := g.Total - g.Claimed329	if g.RevokedAt != 0 {330		owed = claimable(g)331	}332	back := balance(g) - owed333	if back <= 0 {334		return 0335	}336	g.Returned += back337	send(cur, g, to, back)338	chain.Emit("Returned", "id", strconv.FormatInt(g.ID, 10), "to", to.String(), "amount", strconv.FormatInt(back, 10))339	return back340}341342// send moves n of the grant's token out of the grant's own address: the sub-realm is the sender, so one grant can343// never pay from another's balance.344func send(cur realm, g *Grant, to address, n int64) {345	sub := cur.Sub(subpath(g.ID))346	switch kindOf(g.Token) {347	case kindNative:348		banker.NewBanker(banker.BankerTypeRealmSend, sub).SendCoins(sub.Address(), to, chain.Coins{{GNOT, n}})349	case kindBubble:350		bubble.Transfer(cross(sub), to, n)351	default:352		tok := grc20reg.MustGet(g.Token)353		if err := tok.RealmTeller(0, sub).Transfer(0, sub, to, n); err != nil {354			panic("vesting: " + err.Error())355		}356	}357}358359// SetOwner names the next owner; nothing moves until they AcceptOwner. Naming "" withdraws the offer.360func SetOwner(cur realm, id int64, to address) {361	g := get(id)362	mustBeOwner(cur, g)363	if to != "" && !to.IsValid() {364		panic("vesting: not an address")365	}366	if to == g.Beneficiary {367		panic("vesting: the owner cannot be the beneficiary")368	}369	g.OwnerNext = to370	chain.Emit("OwnerNext", "id", strconv.FormatInt(id, 10), "to", to.String())371}372373// AcceptOwner takes the owner role of a grant, by the one named.374func AcceptOwner(cur realm, id int64) {375	g := get(id)376	who := caller(cur)377	if g.OwnerNext == "" || who != g.OwnerNext {378		panic("vesting: not the named next owner")379	}380	g.Owner, g.OwnerNext = who, ""381	chain.Emit("Owner", "id", strconv.FormatInt(id, 10), "to", who.String())382}383384// ----------------------------------------------------------------- pages --385386// Render: "" the newest grants; "<id>" one grant; "json/<id>" its figures in base units; "by/<address>" the grants387// an address owns or receives.388func Render(path string) string {389	parts := strings.Split(path, "/")390	switch {391	case path == "":392		return home()393	case len(parts) == 1:394		id, err := strconv.ParseInt(parts[0], 10, 64)395		if err != nil || id <= 0 || id > last {396			return "404"397		}398		return page(get(id))399	case len(parts) == 2 && parts[0] == "json":400		id, err := strconv.ParseInt(parts[1], 10, 64)401		if err != nil || id <= 0 || id > last {402			return "404"403		}404		return json(get(id))405	case len(parts) == 2 && parts[0] == "by":406		return by(address(parts[1]))407	}408	return "404"409}410411func home() string {412	var b strings.Builder413	b.WriteString("# Vesting grants\n\n")414	b.WriteString(strconv.FormatInt(last, 10) + " grants. Anyone opens one with Create (owner, beneficiary, token, total, up-front share, start, cliff days, days, a note) and funds it by sending the token to the grant's own address; Claim pays the beneficiary what has vested; the owner alone can revoke. Tokens: GNOT, BUBBLE, or any key of the GRC20 registry.\n\n")415	n := 0416	grants.ReverseIterate("", "", func(_ string, v any) bool {417		g := v.(*Grant)418		b.WriteString("- [#" + strconv.FormatInt(g.ID, 10) + "](" + pkgPath + ":" + strconv.FormatInt(g.ID, 10) + ") " + amount(g, g.Total) + " to " + g.Beneficiary.String() + " · " + state(g))419		if g.Note != "" {420			b.WriteString(" · " + g.Note)421		}422		b.WriteString("\n")423		n++424		return n >= listMax425	})426	return b.String()427}428429func page(g *Grant) string {430	var b strings.Builder431	b.WriteString("# Grant #" + strconv.FormatInt(g.ID, 10))432	if g.Note != "" {433		b.WriteString(": " + g.Note)434	}435	b.WriteString("\n\n")436	b.WriteString("- to: " + g.Beneficiary.String() + "\n")437	b.WriteString("- grant: " + amount(g, g.Total) + " — " + amount(g, g.Upfront) + " at the start")438	if g.Days > 0 {439		b.WriteString(", the rest by the day over " + strconv.FormatInt(g.Days, 10) + " days")440	}441	b.WriteString(" from " + date(g.Start))442	if g.CliffDays > 0 {443		b.WriteString("; nothing before " + date(g.Start+g.CliffDays*day) + " (a cliff of " + strconv.FormatInt(g.CliffDays, 10) + " days)")444	}445	b.WriteString("\n")446	b.WriteString("- vested: " + amount(g, vested(g)) + " · paid: " + amount(g, g.Claimed) + " · claimable now: " + amount(g, claimable(g)) + " · held at the grant's address: " + amount(g, balance(g)) + "\n")447	b.WriteString("- state: " + state(g))448	switch {449	case g.Voided:450		b.WriteString(" — revoked on " + date(g.RevokedAt) + " before anything arrived; nothing vests; " + amount(g, g.Returned) + " went back to the owner")451	case g.RevokedAt != 0:452		b.WriteString(" — revoked on " + date(g.RevokedAt) + "; the schedule stopped there; " + amount(g, g.Returned) + " went back to the owner")453	case g.Owner == "":454		b.WriteString(" — irrevocable: nobody can end it; anything beyond the grant is the beneficiary's (Sweep)")455	default:456		b.WriteString(" — the owner can revoke; what has vested by then stays the beneficiary's")457	}458	b.WriteString("\n")459	if g.Owner != "" {460		b.WriteString("- owner: " + g.Owner.String())461		if g.OwnerNext != "" {462			b.WriteString(" (hand-off offered to " + g.OwnerNext.String() + ")")463		}464		b.WriteString("\n")465	}466	b.WriteString("- opened by: " + g.Creator.String() + "\n")467	b.WriteString("- token: " + g.Token + "\n")468	b.WriteString("- the grant's address, to fund it: " + chain.DerivePkgSubAddr(pkgPath, subpath(g.ID)).String() + "\n\n")469	b.WriteString("Claim pays the beneficiary what has vested and not been paid; anyone may call it. A token held here carries no vote until it is claimed.\n")470	return b.String()471}472473func by(who address) string {474	if !who.IsValid() { // the path is anyone's text: only an address is echoed onto the page475		return "404"476	}477	var b strings.Builder478	b.WriteString("# Grants of " + who.String() + "\n\n")479	n := 0480	grants.ReverseIterate("", "", func(_ string, v any) bool {481		g := v.(*Grant)482		if g.Owner != who && g.Beneficiary != who {483			return false484		}485		role := "receives"486		if g.Owner == who {487			role = "owns"488		}489		b.WriteString("- " + role + " [#" + strconv.FormatInt(g.ID, 10) + "](" + pkgPath + ":" + strconv.FormatInt(g.ID, 10) + ") " + amount(g, g.Total) + " · " + state(g) + "\n")490		n++491		return n >= listMax492	})493	if n == 0 {494		b.WriteString("none\n")495	}496	return b.String()497}498499func json(g *Grant) string {500	return `{"id":` + strconv.FormatInt(g.ID, 10) + `,"token":"` + g.Token + `","beneficiary":"` + g.Beneficiary.String() + `","owner":"` + g.Owner.String() + `","ownerNext":"` + g.OwnerNext.String() + `","creator":"` + g.Creator.String() +501		`","address":"` + chain.DerivePkgSubAddr(pkgPath, subpath(g.ID)).String() + `","total":` + strconv.FormatInt(g.Total, 10) + `,"upfront":` + strconv.FormatInt(g.Upfront, 10) +502		`,"start":` + strconv.FormatInt(g.Start, 10) + `,"cliffDays":` + strconv.FormatInt(g.CliffDays, 10) + `,"days":` + strconv.FormatInt(g.Days, 10) +503		`,"vested":` + strconv.FormatInt(vested(g), 10) + `,"claimed":` + strconv.FormatInt(g.Claimed, 10) + `,"claimable":` + strconv.FormatInt(claimable(g), 10) + `,"balance":` + strconv.FormatInt(balance(g), 10) +504		`,"revokedAt":` + strconv.FormatInt(g.RevokedAt, 10) + `,"voided":` + strconv.FormatBool(g.Voided) + `,"returned":` + strconv.FormatInt(g.Returned, 10) + `,"note":"` + strings.ReplaceAll(g.Note, `"`, `\"`) + `"}`505}506507func state(g *Grant) string {508	switch {509	case g.Voided:510		return "voided"511	case g.RevokedAt != 0:512		return "revoked"513	case g.Claimed >= g.Total:514		return "paid in full"515	case time.Now().Unix() < g.Start:516		return "not started"517	}518	return "running"519}520521func date(unix int64) string { return time.Unix(unix, 0).UTC().Format("2006-01-02") }522523// amount prints base units in the token's own unit, trailing zeros dropped.524func amount(g *Grant, n int64) string {525	decimals, symbol := 6, "GNOT"526	switch kindOf(g.Token) {527	case kindBubble:528		symbol = "BUBBLE"529	case kindRegistry:530		tok := grc20reg.MustGet(g.Token)531		decimals, symbol = tok.GetDecimals(), tok.GetSymbol()532	}533	one := int64(1)534	for i := 0; i < decimals; i++ {535		one *= 10536	}537	whole, frac := n/one, n%one538	s := strconv.FormatInt(whole, 10)539	if frac != 0 {540		f := strconv.FormatInt(frac, 10)541		for len(f) < decimals {542			f = "0" + f543		}544		s += "." + strings.TrimRight(f, "0")545	}546	return s + " " + symbol547}548

Functions

  • AcceptOwner(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64)

  • Address(id int64) string

  • Balance(id int64) int64

  • Claim(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64) int64

  • Claimable(id int64) int64

  • Count() int64

  • Create(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, owner string, beneficiary string, token string, total int64, upfront int64, start int64, cliffDays int64, days int64, note string) int64

  • Get(id int64) struct{ID int64; Token string; Creator .uverse.address; Owner .uverse.address; OwnerNext .uverse.address; Beneficiary .uverse.address; Total int64; Upfront int64; Start int64; CliffDays int64; Days int64; Claimed int64; Returned int64; RevokedAt int64; Voided bool; Note string}

  • Render(path string) string

  • Revoke(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64) int64

  • SetOwner(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64, to string)

  • Sweep(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64) int64

  • Vested(id int64) int64

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.