Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

wugnot.gno

2.69 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/nt/grc20/v0"
 11	"gno.land/p/nt/ufmt/v0"
 12	"gno.land/r/nt/grc20reg/v0"
 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 := adm.CallerTeller()
 91	checkErr(userTeller.Transfer(0, cur, to, amount))
 92}
 93
 94func Approve(cur realm, spender address, amount int64) {
 95	userTeller := adm.CallerTeller()
 96	checkErr(userTeller.Approve(0, cur, spender, amount))
 97}
 98
 99func TransferFrom(cur realm, from, to address, amount int64) {
100	userTeller := adm.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}