← Back to Realms

Realm

gno.land/r/moul/x/reaper/v1

Overview

Realm Path
gno.land/r/moul/x/reaper/v1
Exported Functions
8
State Entries
4
Source Files
4
Total Package Entries
15

Exported Functions

8 exported functions

State

4 state entries

Source Code

FILES
example_test.gno
go
1package reaper
2
3import (
4	"strings"
5
6	"gno.land/p/moul/x/storagecost/v0"
7	"gno.land/p/nt/ufmt/v0"
8)
9
10// Every Example in this file is a *query*, and that is a constraint rather
11// than a choice: an example function takes no arguments, so it never receives
12// a `cur realm` and can never call Post, Reap or Compact. What is left is
13// exactly the surface a reader of the live realm has without a key, so each
14// one carries the `vm/qeval` line that produces the same answer on chain:
15//
16//	gnokey query vm/qeval -remote https://rpc.gno.land \
17//	  -data 'gno.land/r/moul/x/reaper/v0.<expr>'
18//
19// The board is empty by the time these run, because every Test in this
20// package drains what it posted and examples run after all of them.
21
22// ExampleRender pins the page's skeleton: the title, the two sections that are
23// always present, and the footer crediting the two packages that own the parts
24// this realm does not.
25//
26//	vm/qrender  gno.land/r/moul/x/reaper/v0:
27//
28// It deliberately prints only the invariant lines. Everything interesting on
29// the page is priced from the current block height and the notes outstanding,
30// and an Example runs after every Test in the package and sees whatever state
31// they left. The variable half is pinned by TestRenderShowsTheBountyAndTheReapLink
32// instead, which controls the board first.
33func ExampleRender() {
34	for _, line := range strings.Split(Render(""), "\n") {
35		switch {
36		case strings.HasPrefix(line, "# "),
37			strings.HasPrefix(line, "## "),
38			strings.HasPrefix(line, "A noticeboard"),
39			strings.HasPrefix(line, "The arithmetic is"):
40			print(line + "\n")
41		}
42	}
43	// Output:
44	// # Reaper
45	// A noticeboard whose garbage is a standing bounty. Posting a note locks a storage deposit. Once the note expires, anyone can delete it and the chain refunds that deposit **to whoever signs the deleting transaction**.
46	// ## On the table right now
47	// ## Board
48	// The arithmetic is [p/moul/x/storagecost](/p/moul/x/storagecost/v0); the storage is [p/moul/ulist](/p/moul/ulist/v1), whose `Compact` reclaims dead nodes without moving a live index. Byte figures on this page are estimates from payload length: no stdlib call exposes a realm's real locked storage.
49}
50
51// ExampleReapable is the poll a reaping bot runs before it spends anything:
52// three counters, three queries, no key and no gas.
53//
54//	vm/qeval  gno.land/r/moul/x/reaper/v0.Live()
55//	vm/qeval  gno.land/r/moul/x/reaper/v0.Reapable()
56//	vm/qeval  gno.land/r/moul/x/reaper/v0.Compactable()
57//
58// Reapable and Compactable are separate numbers because reaping and
59// compacting are separate transactions, and compaction returns nothing at all
60// while a live note still sits below the dead ones. A bot that sees
61// `reapable 0, compactable 0` should not sign anything, which is the answer
62// here.
63func ExampleReapable() {
64	print(ufmt.Sprintf("live %d, reapable %d, compactable %d\n",
65		Live(), Reapable(), Compactable()))
66	// Output:
67	// live 0, reapable 0, compactable 0
68}
69
70// ExampleBounty is the single query that decides whether reaping is worth
71// doing, and on an empty board it has to refuse to advertise a profit.
72//
73//	vm/qeval  gno.land/r/moul/x/reaper/v0.Bounty().String()
74//
75// Fee is what the reaping transaction costs at the floor gas price, and the
76// chain charges it whether or not anything is freed. BreakEven turns that fee
77// back into bytes: free fewer than 50 and the reaper is paying to tidy up.
78// That threshold, not the size of the board, is what makes the mechanism a
79// market rather than a chore.
80func ExampleBounty() {
81	print(Bounty().String() + "\n")
82	// Output:
83	// 0 bytes, refunds 0 GNOT against 0.005 GNOT of gas, break-even 50 bytes: not worth it yet
84}
85
86// ExampleBounty_worth is the same query answered by a board worth draining:
87// ten expired notes of a kilobyte each.
88//
89// It recomputes the quote instead of posting, because an example has no
90// `cur realm` to post with. The arithmetic is the one Bounty applies, so the
91// numbers are the ones the live query would return with that board on it.
92//
93// This is the whole concept in two lines. The poster locked 1.8944 GNOT to
94// occupy that space; a stranger who never posted anything spends 0.005 GNOT of
95// gas to delete it and the chain hands them the deposit. Nobody minted a
96// token, and no pool was funded.
97func ExampleBounty_worth() {
98	q := storagecost.EvaluateAtFloor(storagecost.EstimateBytes(10*1024), gasWantedReap)
99	print(q.String() + "\n")
100	print(ufmt.Sprintf("the reaper is paid %dx what the transaction costs\n", q.Refund/q.Fee))
101	// Output:
102	// 18944 bytes, refunds 1.8944 GNOT against 0.005 GNOT of gas, break-even 50 bytes: worth 1.8894 GNOT
103	// the reaper is paid 378x what the transaction costs
104}
105

Raw Package Data

Raw JSON data