wugnot.gno
2.64 Kb · 113 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 Token, adm = grc20.NewToken(0, cur, "wrapped GNOT", "wugnot", 0)
27 grc20reg.Register(cross(cur), Token, "")
28}
29
30func Deposit(cur realm) {
31 // Prevent cross-realm MITM: without this, an intermediary could
32 // deposit on behalf of the caller and mint wugnot to itself
33 // instead of the actual sender.
34 runtime.AssertOriginCall()
35 caller := cur.Previous().Address()
36 sent := unsafe.OriginSend()
37 amount := sent.AmountOf("ugnot")
38
39 require(int64(amount) >= ugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d ugnot.", amount, ugnotMinDeposit))
40
41 checkErr(adm.Mint(caller, int64(amount)))
42}
43
44func Withdraw(cur realm, amount int64) {
45 runtime.AssertOriginCall()
46 require(amount >= wugnotMinDeposit, ufmt.Sprintf("Deposit below minimum: %d/%d wugnot.", amount, wugnotMinDeposit))
47
48 caller := cur.Previous().Address()
49 pkgaddr := cur.Address()
50 callerBal := Token.BalanceOf(caller)
51 require(amount <= callerBal, ufmt.Sprintf("Insufficient balance: %d available, %d needed.", callerBal, amount))
52
53 // send swapped ugnots to qcaller
54 stdBanker := banker.NewBanker(banker.BankerTypeRealmSend, cur)
55 send := chain.Coins{{"ugnot", int64(amount)}}
56 stdBanker.SendCoins(pkgaddr, caller, send)
57 checkErr(adm.Burn(caller, amount))
58}
59
60func Render(path string) string {
61 parts := strings.Split(path, "/")
62 c := len(parts)
63
64 switch {
65 case path == "":
66 return Token.RenderHome()
67 case c == 2 && parts[0] == "balance":
68 owner := address(parts[1])
69 balance := Token.BalanceOf(owner)
70 return ufmt.Sprintf("%d", balance)
71 default:
72 return "404"
73 }
74}
75
76func TotalSupply() int64 {
77 return Token.TotalSupply()
78}
79
80func BalanceOf(owner address) int64 {
81 return Token.BalanceOf(owner)
82}
83
84func Allowance(owner, spender address) int64 {
85 return Token.Allowance(owner, spender)
86}
87
88func Transfer(cur realm, to address, amount int64) {
89 userTeller := Token.CallerTeller()
90 checkErr(userTeller.Transfer(0, cur, to, amount))
91}
92
93func Approve(cur realm, spender address, amount int64) {
94 userTeller := Token.CallerTeller()
95 checkErr(userTeller.Approve(0, cur, spender, amount))
96}
97
98func TransferFrom(cur realm, from, to address, amount int64) {
99 userTeller := Token.CallerTeller()
100 checkErr(userTeller.TransferFrom(0, cur, from, to, amount))
101}
102
103func require(condition bool, msg string) {
104 if !condition {
105 panic(msg)
106 }
107}
108
109func checkErr(err error) {
110 if err != nil {
111 panic(err)
112 }
113}