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/g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp/hlfees

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
hlfees
Namespace
g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp
Files
2 (gnomod.toml)
Exported functions
9
Module
gno.land/r/g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp/hlfees
gno
0.9

Files (2)

  • gnomod.tomltoml
  • hlfees.gnogno
hlfees.gnogno
1// Package hlfees is the bridge's fee realm (bridge/PLAN.md §5.5): the routes pay every fee here — GNOT as coins,2// BUBBLE through the token realm — and only the treasurer a decision names may withdraw, to itself. The treasurer3// at launch is compiled in below; a decision made with the builder changes it, 7 days after it is made — the4// governor's own through Govern until it yields on r/hlmailbox, a GovDAO proposal's after (M1k).5package hlfees67import (8	"chain"9	"chain/banker"10	"strconv"11	"strings"12	"time"1314	"gno.land/p/g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp/decisions/v0"15	"gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/bubble"16	"gno.land/r/g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp/hlmailbox"17	"gno.land/r/gov/dao"18)1920const (21	namespace = "gno.land/r/g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp/"22	pkgPath   = namespace + "hlfees" // must match gnomod.toml2324	// launchTreasurer is the operator's named key (§5.5, §11.12): a PLACEHOLDER — the deployer's hotkey — until25	// the launch notice names it; GovDAO can name the chain's own address instead at any vote.26	launchTreasurer = address("g1zdaz6sypk5tdsjc2fzsqrrn4ttn8qzmnl4waqp")27)2829// launchGovernor is the governor (M1k): the mailbox's, compiled here too so a member reads it in this realm's30// served source; init refuses a deploy with another. bridge/local/e2e.sh swaps it for gnodev's test1.31const launchGovernor = address("g1ecsuj0q572jr0dhu29q9njtnmw03hyu7tyyvv6")3233var (34	treasurer = launchTreasurer35	ledger    decisions.Ledger36)3738// init refuses a deploy whose compiled governor is not the mailbox's (M1k): the bridge's realms are governed by39// one key until it yields, or by GovDAO from the first block, never a mix.40func init() {41	if launchGovernor != hlmailbox.Governor() {42		panic("hlfees: the compiled governor " + string(launchGovernor) + " is not the mailbox's " + string(hlmailbox.Governor()))43	}44}4546type (47	treasurerParams struct{ to address }48	cancelParams    struct{ id int64 }49)5051func now() int64 { return time.Now().Unix() }5253func itoa(n int64) string { return strconv.FormatInt(n, 10) }5455// Address is this realm's address: where the routes pay the fees.56func Address() address { return chain.PackageAddress(pkgPath) }5758// Treasurer is the one address that may withdraw.59func Treasurer() address { return treasurer }6061// Balances are the fees held: ugnot and BUBBLE base units.62func Balances() (ugnot, bubbles int64) {63	return banker.NewReadonlyBanker().GetCoin(Address(), "ugnot"), bubble.BalanceOf(Address())64}6566// Withdraw pays everything held to the treasurer, who alone may call it.67func Withdraw(cur realm) {68	if !cur.IsCurrent() {69		panic("hlfees: that realm value is not live; pass your own cur")70	}71	if cur.Previous().Address() != treasurer {72		panic("hlfees: only the treasurer withdraws")73	}74	ugnot, bubbles := Balances()75	if ugnot > 0 {76		banker.NewBanker(banker.BankerTypeRealmSend, cur).SendCoins(Address(), treasurer, chain.Coins{{"ugnot", ugnot}})77	}78	if bubbles > 0 {79		bubble.Transfer(cross(cur), treasurer, bubbles)80	}81	chain.Emit("Withdrawn", "to", string(treasurer), "ugnot", itoa(ugnot), "bubble", itoa(bubbles))82}8384// ------------------------------------------------------------ builders --8586// Request is what a builder returns (M1k): the proposal GovDAO's proxy executes after the yield (Proposal), and87// the same decision the governor runs directly before it (Govern); see hlgnot's.88type Request struct {89	proposal dao.ProposalRequest90	text     string91	decide   func(cur realm) error92}9394// Proposal is the request as a GovDAO proposal: `dao.MustCreateProposal(cross(cur), req.Proposal())`.95func (r Request) Proposal() dao.ProposalRequest { return r.proposal }9697// Description is the proposal's: the parameters as the builder wrote them.98func (r Request) Description() string { return r.text }99100// who names a previous realm in a refusal: its pkgpath, or a user's address.101func who(path string, a address) string {102	if path != "" {103		return path104	}105	return string(a)106}107108// mustBeGovernor is a decision's identity check (M1k), read from the closure's own live cur: the governor's own109// call until it yields on r/hlmailbox, gno.land/r/gov/dao's proxy exactly after (or from the first block, when no110// governor was compiled); see hlgnot's.111func mustBeGovernor(cur realm) {112	prev := cur.Previous()113	if decisions.DAOGoverns(launchGovernor, hlmailbox.Yielded()) {114		if p := prev.PkgPath(); p != decisions.DAOPath {115			panic("hlfees: only " + decisions.DAOPath + " executes a decision, not " + who(prev.PkgPath(), prev.Address()))116		}117		return118	}119	if !prev.IsUser() || prev.Address() != launchGovernor {120		panic("hlfees: until the governor yields, " + string(launchGovernor) + " alone decides, by Govern from its own key: not " + who(prev.PkgPath(), prev.Address()) + " (a GovDAO proposal is refused until the yield)")121	}122}123124func mustBeLive() {125	if !hlmailbox.Live() {126		panic("hlfees: not launched: before the Launch decision only cancel is proposed")127	}128}129130func propose(cur realm, kind, text string, apply func(made, t int64)) Request {131	if !cur.IsCurrent() {132		panic("hlfees: that realm value is not live; pass your own cur")133	}134	made := now()135	cb := func(cur realm) error {136		mustBeGovernor(cur)137		t := now()138		if err := decisions.Expired(made, t); err != nil {139			return err140		}141		apply(made, t)142		return nil143	}144	return Request{proposal: dao.NewProposalRequest("hlfees: "+kind, text, dao.NewSimpleExecutor(0, cur, cb, text)), text: text, decide: cb}145}146147// Govern is the governor's way in before the yield (M1k): the same closure GovDAO's proxy runs after it, called148// non-crossing in this frame so it reads the governor from cur.Previous(); refused for anyone else and for149// everyone once the governor yielded on r/hlmailbox (or when none was compiled); see hlgnot's.150func Govern(cur realm, r Request) {151	if !cur.IsCurrent() {152		panic("hlfees: that realm value is not live; pass your own cur")153	}154	if r.decide == nil {155		panic("hlfees: not a builder's request")156	}157	if yielded := hlmailbox.Yielded(); decisions.DAOGoverns(launchGovernor, yielded) {158		if launchGovernor == "" {159			panic("hlfees: no governor was compiled, " + decisions.DAOPath + " governs from the first block: a decision is a GovDAO proposal, never Govern")160		}161		panic("hlfees: the governor yielded at height " + itoa(yielded) + ", " + decisions.DAOPath + " governs since: a decision is a GovDAO proposal, never Govern")162	}163	mustBeGovernor(cur)164	if err := r.decide(cur); err != nil {165		panic("hlfees: " + err.Error())166	}167}168169// NewSetTreasurerRequest names the address that may withdraw, 7 days after the decision is made.170func NewSetTreasurerRequest(cur realm, to address) Request {171	mustBeLive()172	if !to.IsValid() {173		panic("hlfees: not an address: " + string(to))174	}175	if to == treasurer {176		panic("hlfees: " + string(to) + " is the treasurer already")177	}178	text := "set treasurer to " + string(to) + " (now " + string(treasurer) + ")"179	return propose(cur, "set treasurer", text, func(made, t int64) {180		mustBeLive()181		d := ledger.Record("set treasurer", text, treasurerParams{to}, made, t, t+decisions.Delay)182		d.Note = "queued 7 days"183		chain.Emit("Decision", "id", itoa(d.ID), "kind", "set treasurer", "state", "queued")184	})185}186187// NewCancelRequest cancels a pending decision of this realm, at once.188func NewCancelRequest(cur realm, id int64) Request {189	d := ledger.Get(id)190	if d == nil || !d.Pending() {191		panic("hlfees: decision " + itoa(id) + " is not pending")192	}193	text := "cancel decision " + itoa(id) + " (" + d.Text + ")"194	return propose(cur, "cancel", text, func(made, t int64) {195		if _, err := ledger.Cancel(id, t); err != nil {196			panic("hlfees: " + err.Error())197		}198		c := ledger.Record("cancel", text, cancelParams{id}, made, t, t)199		ledger.Apply(c, t, "at once: cancelled")200	})201}202203// Execute applies a queued decision whose 7 days have passed; anyone may call it.204func Execute(cur realm, id int64) {205	if !cur.IsCurrent() {206		panic("hlfees: that realm value is not live; pass your own cur")207	}208	t := now()209	d, err := ledger.Due(id, t)210	if err != nil {211		panic("hlfees: " + err.Error())212	}213	p, ok := d.Params.(treasurerParams)214	if !ok {215		panic("hlfees: decision " + itoa(id) + " has nothing to apply")216	}217	treasurer = p.to218	ledger.Apply(d, t, "applied after the delay")219	chain.Emit("TreasurerSet", "address", string(treasurer))220}221222// --------------------------------------------------------------- pages --223224// Render: "" the page; "json" the figures; "decisions" and "decisions.json" the decisions.225func Render(path string) string {226	ugnot, bubbles := Balances()227	switch path {228	case "":229		var b strings.Builder230		b.WriteString("# The bridge's fees\n\n")231		b.WriteString("Every fee the bridge takes lands here: GNOT as coins, BUBBLE as the token. Only the treasurer a decision names withdraws, to itself.\n\n")232		b.WriteString("- held: " + itoa(ugnot) + " ugnot, " + itoa(bubbles) + " BUBBLE base units\n")233		b.WriteString("- treasurer: " + string(treasurer) + "\n")234		b.WriteString("- " + decisions.GovernorLine(launchGovernor, hlmailbox.Yielded()) + "\n")235		b.WriteString("- " + decisions.Clocks() + "\n")236		b.WriteString("\n## Decisions\n\n" + ledger.Page())237		return b.String()238	case "json":239		return "{\"address\":" + strconv.Quote(string(Address())) + ",\"treasurer\":" + strconv.Quote(string(treasurer)) +240			"," + decisions.GovernorJSON(launchGovernor, hlmailbox.Yielded()) +241			",\"ugnot\":" + itoa(ugnot) + ",\"bubble\":" + itoa(bubbles) + ",\"clocks\":" + decisions.ClocksJSON() + ",\"decisions\":" + itoa(ledger.Last()) + "}"242	case "decisions":243		return "# Decisions\n\n" + ledger.Page()244	case "decisions.json":245		return ledger.JSON()246	}247	return "unknown path; see the page"248}249

Functions

  • Address() string

  • Balances() (ugnot int64, bubbles int64)

  • Execute(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)

  • Govern(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}, r struct{proposal gno.land/r/gov/dao.ProposalRequest; text string; decide func(.uverse.realm) .uverse.error})

  • NewCancelRequest(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) struct{proposal gno.land/r/gov/dao.ProposalRequest; text string; decide func(.uverse.realm) .uverse.error}

  • NewSetTreasurerRequest(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}, to string) struct{proposal gno.land/r/gov/dao.ProposalRequest; text string; decide func(.uverse.realm) .uverse.error}

  • Render(path string) string

  • Treasurer() string

  • Withdraw(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})

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.