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

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}