wugnot.gno
2.71 Kb · 114 lines
1package wugnot
2
3import (
4 "chain"
5 "chain/banker"
6 "chain/runtime"
7 "chain/runtime/unsafe"
8 "strings"
9
10 "gno.land/p/demo/tokens/grc20"
11 "gno.land/p/nt/ufmt/v0"
12 "gno.land/r/demo/defi/grc20reg"
13)
14
15var (
16 Token *grc20.Token
17 adm *grc20.PrivateLedger
18)
19
20const (
21 ugnotMinDeposit int64 = 1000
22 wugnotMinDeposit int64 = 1
23)
24
25func init(cur realm) {
26 // wugnot only ever creates this one token, so id 0 can't collide.
27 Token, adm = grc20.NewToken("wrapped GNOT", "wugnot", 0, 0, cur)
28 grc20reg.Register(cross(cur), Token, "")
29}
30
31func Deposit(cur realm) {
32 // Prevent cross-realm MITM: without this, an intermediary could
33 // deposit on behalf of the caller and mint wugnot to itself
34 // instead of the actual sender.
35 runtime.AssertOriginCall()
36 caller := cur.Previous().Address()
37 sent := unsafe.OriginSend()
38 amount := sent.AmountOf("ugnot")
39
40 require(int64(amount) >= ugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d ugnot.", amount, ugnotMinDeposit))
41
42 checkErr(adm.Mint(caller, int64(amount)))
43}
44
45func Withdraw(cur realm, amount int64) {
46 runtime.AssertOriginCall()
47 require(amount >= wugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d wugnot.", amount, wugnotMinDeposit))
48
49 caller := cur.Previous().Address()
50 pkgaddr := cur.Address()
51 callerBal := Token.BalanceOf(caller)
52 require(amount <= callerBal, ufmt.Sprintf("Insufficient balance: %d available, %d needed.", callerBal, amount))
53
54 // send swapped ugnots to qcaller
55 stdBanker := banker.NewBanker(banker.BankerTypeRealmSend, cur)
56 send := chain.Coins{{"ugnot", int64(amount)}}
57 stdBanker.SendCoins(pkgaddr, caller, send)
58 checkErr(adm.Burn(caller, amount))
59}
60
61func Render(path string) string {
62 parts := strings.Split(path, "/")
63 c := len(parts)
64
65 switch {
66 case path == "":
67 return Token.RenderHome()
68 case c == 2 && parts[0] == "balance":
69 owner := address(parts[1])
70 balance := Token.BalanceOf(owner)
71 return ufmt.Sprintf("%d", balance)
72 default:
73 return "404"
74 }
75}
76
77func TotalSupply() int64 {
78 return Token.TotalSupply()
79}
80
81func BalanceOf(owner address) int64 {
82 return Token.BalanceOf(owner)
83}
84
85func Allowance(owner, spender address) int64 {
86 return Token.Allowance(owner, spender)
87}
88
89func Transfer(cur realm, to address, amount int64) {
90 userTeller := Token.CallerTeller()
91 checkErr(userTeller.Transfer(0, cur, to, amount))
92}
93
94func Approve(cur realm, spender address, amount int64) {
95 userTeller := Token.CallerTeller()
96 checkErr(userTeller.Approve(0, cur, spender, amount))
97}
98
99func TransferFrom(cur realm, from, to address, amount int64) {
100 userTeller := Token.CallerTeller()
101 checkErr(userTeller.TransferFrom(0, cur, from, to, amount))
102}
103
104func require(condition bool, msg string) {
105 if !condition {
106 panic(msg)
107 }
108}
109
110func checkErr(err error) {
111 if err != nil {
112 panic(err)
113 }
114}