token.gno
3.76 Kb · 81 lines
1// Package bubble is BUBBLE, the Bubble Rumble token: a GRC20 that remembers voting power (kourt's grc20votes),
2// minted by the box for referrals under hard caps, and governed by kourt's governor on the same ledger.
3//
4// What is fixed here and what is not. The identity, the decimals, the max supply, the premine and the split
5// between the referral pool and the reserve are constants: a realm cannot be redeployed at its path, so a number
6// that must never move is a constant, not a setting. Who administers, who mints, whether minting is paused and
7// how much may be minted a day are settings — the admin's until the holders vote them away (kinds.gno).
8//
9// The box (presence/bubble.go) decides which referral earns what; this realm only enforces the walls: the
10// supply, the pools, the daily ceiling, the batch shape. See growth/BUBBLE.md.
11package bubble
12
13import (
14 grc20votes "gno.land/p/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/grc20votes/v0"
15)
16
17const (
18 tokenName = "Bubble"
19 tokenSymbol = "BUBBLE"
20 tokenDecimals = 6
21 pkgPath = "gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/bubble" // must match gnomod.toml
22 tokenID = pkgPath + "." + tokenSymbol
23
24 // One BUBBLE in base units.
25 one = int64(1_000_000)
26
27 // epochBlocks quantises the voting snapshots: about 55 minutes at gnoland-1's 3.3 s blocks (kourt uses 720 at
28 // the 5 s it was measured at). A vote is weighed at the last sealed epoch, so weight bought after a question is
29 // asked does not count.
30 epochBlocks = int64(1000)
31)
32
33// ledger is the token. Unexported and never handed out: whoever holds a *Ledger can mint.
34var ledger = grc20votes.NewLedger(tokenName, tokenSymbol, tokenDecimals, epochBlocks)
35
36// ---------------------------------------------------------------- reading --
37
38func GetName() string { return ledger.Name() }
39func GetSymbol() string { return ledger.Symbol() }
40func GetDecimals() int { return ledger.Decimals() }
41func TotalSupply() int64 { return ledger.TotalSupply() }
42
43func BalanceOf(owner address) int64 { return ledger.BalanceOf(owner) }
44func Allowance(owner, spender address) int64 { return ledger.Allowance(owner, spender) }
45func VotesOf(who address) int64 { return ledger.VotesOf(who) }
46func DelegateOf(who address) address { return ledger.DelegateOf(who) }
47func PastVotes(who address, at uint32) int64 { return ledger.PastVotes(who, at) }
48func PastTotalVotes(at uint32) int64 { return ledger.PastTotal(at) }
49func Epoch() uint32 { return ledger.Epoch() }
50
51// ---------------------------------------------------------------- writing --
52//
53// Refuse a stale realm value, read who is calling, hand the ledger an address: kourt's three lines, because the
54// ledger (a /p/ package) has no caller to read.
55
56const errStaleRealm = "bubble: that realm value is not live; pass your own cur"
57
58func caller(cur realm) address {
59 if !cur.IsCurrent() {
60 panic(errStaleRealm)
61 }
62 return cur.Previous().Address()
63}
64
65// Transfer moves the caller's own tokens.
66func Transfer(cur realm, to address, amount int64) { ledger.Transfer(caller(cur), to, amount) }
67
68// Approve lets a spender move some of the caller's balance.
69func Approve(cur realm, spender address, amount int64) { ledger.Approve(caller(cur), spender, amount) }
70
71// TransferFrom spends an allowance.
72func TransferFrom(cur realm, from, to address, amount int64) {
73 ledger.TransferFrom(caller(cur), from, to, amount)
74}
75
76// Burn destroys the caller's own tokens. What is burned is gone from the supply and never re-minted: the pools
77// count what was minted, not what exists.
78func Burn(cur realm, amount int64) { ledger.Burn(caller(cur), amount) }
79
80// Delegate points the caller's voting power at someone else (one hop; self is the default).
81func Delegate(cur realm, to address) { ledger.Delegate(caller(cur), to) }