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

abt.gno

3.12 Kb · 105 lines
  1package abt
  2
  3import (
  4	"chain"
  5	"chain/runtime/unsafe"
  6	"strconv"
  7
  8	"gno.land/p/akkadia/beta/accesscontrol"
  9	"gno.land/p/nt/grc20/v0"
 10	"gno.land/r/akkadia/beta/admin"
 11)
 12
 13const FrozenChangedEvent = "FrozenChanged"
 14
 15var (
 16	// Even a Token can create mutable tellers; keep all capabilities private.
 17	token  *grc20.Token
 18	ledger *grc20.PrivateLedger
 19	frozen = true
 20)
 21
 22func init(cur realm) {
 23	token, ledger = grc20.NewToken("Akkadia Beta Token", "abt", 6, 0, cur)
 24}
 25
 26// Mint remains available while frozen. Each successful call issues new tokens.
 27func Mint(cur realm, to address, amount int64) {
 28	accesscontrol.MustGetAdminOrOperatorCaller(0, cur, admin.IsAdmin, admin.IsOperator)
 29	assertNoCoins(0, cur)
 30	if !to.IsValid() {
 31		panic("invalid abt recipient")
 32	}
 33	if amount <= 0 {
 34		panic("abt amount must be positive")
 35	}
 36	if err := ledger.Mint(to, amount); err != nil {
 37		panic("abt mint failed: " + err.Error())
 38	}
 39}
 40
 41// SetFrozen preserves existing allowances, which become usable after unfreezing.
 42func SetFrozen(cur realm, value bool) {
 43	caller := accesscontrol.MustGetAdminCaller(0, cur, admin.IsAdmin)
 44	assertNoCoins(0, cur)
 45	if frozen == value {
 46		return
 47	}
 48	previous := frozen
 49	frozen = value
 50	chain.Emit(FrozenChangedEvent,
 51		"executor", caller.String(),
 52		"previous", strconv.FormatBool(previous),
 53		"frozen", strconv.FormatBool(frozen),
 54	)
 55}
 56
 57func Transfer(cur realm, to address, amount int64) {
 58	assertCanTransfer(0, cur)
 59	if err := ledger.CallerTeller().Transfer(0, cur, to, amount); err != nil {
 60		panic("abt transfer failed: " + err.Error())
 61	}
 62}
 63
 64// Approve also rejects allowance revocation while frozen.
 65func Approve(cur realm, spender address, amount int64) {
 66	assertCanTransfer(0, cur)
 67	if err := ledger.CallerTeller().Approve(0, cur, spender, amount); err != nil {
 68		panic("abt approval failed: " + err.Error())
 69	}
 70}
 71
 72func TransferFrom(cur realm, from, to address, amount int64) {
 73	assertCanTransfer(0, cur)
 74	// The library spends allowance before rejecting self-transfers. Reject
 75	// here so even a caller that revives the abort cannot consume allowance.
 76	if from == to {
 77		panic("abt transfer failed: cannot send transfer to self")
 78	}
 79	if err := ledger.CallerTeller().TransferFrom(0, cur, from, to, amount); err != nil {
 80		panic("abt transfer failed: " + err.Error())
 81	}
 82}
 83
 84func IsFrozen() bool                         { return frozen }
 85func GetName() string                        { return token.GetName() }
 86func GetSymbol() string                      { return token.GetSymbol() }
 87func GetDecimals() int                       { return token.GetDecimals() }
 88func TotalSupply() int64                     { return token.TotalSupply() }
 89func BalanceOf(owner address) int64          { return token.BalanceOf(owner) }
 90func Allowance(owner, spender address) int64 { return token.Allowance(owner, spender) }
 91
 92func assertCanTransfer(_ int, rlm realm) {
 93	accesscontrol.AssertCurrentRealm(0, rlm)
 94	assertNoCoins(0, rlm)
 95	if frozen {
 96		panic("abt is frozen")
 97	}
 98}
 99
100func assertNoCoins(_ int, rlm realm) {
101	// OriginSend belongs to the origin call, not a subsequent realm relay.
102	if rlm.Previous().IsUser() && len(unsafe.OriginSend()) != 0 {
103		panic("attached coins not allowed")
104	}
105}