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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

redeem.gno

3.33 Kb · 118 lines
  1package kourtv3
  2import (
  3	"chain"
  4	"chain/banker"
  5	"chain/runtime/unsafe"
  6	"strconv"
  7	"gno.land/p/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/grc20votes/v0"
  8)
  9const (
 10	burnBpsInit = int64(1000)
 11	minBurnBps = int64(500)
 12	maxBurnBps = int64(5000)
 13	bpsDenom = grc20votes.Bps
 14	coinUnit = int64(1_000_000)
 15	boughtEvent   = "Bought"
 16	redeemedEvent = "Redeemed"
 17)
 18var burnBps = burnBpsInit
 19var totalReserve int64
 20func BurnBps() int64 { return burnBps }
 21func SetBurnBps(cur realm, bps int64) {
 22	if !cur.IsCurrent() {
 23		panic(errStaleRealm)
 24	}
 25	d := ensureGlobalDAO()
 26	if cur.Previous().Address() != d.admin {
 27		panic("kourtv3: only the global DAO admin sets the burn share")
 28	}
 29	mustSaneBurnBps(bps)
 30	old := burnBps
 31	burnBps = bps
 32	chain.Emit(globalActEvent,
 33		"court", "*",
 34		"claim", "0",
 35		"act", "set-burn-bps:"+strconv.FormatInt(old, 10)+"->"+strconv.FormatInt(bps, 10),
 36		"by", cur.Previous().Address().String(),
 37		"height", eventHeight(),
 38	)
 39}
 40func mustSaneBurnBps(bps int64) {
 41	if bps < minBurnBps || bps > maxBurnBps {
 42		panic("kourtv3: the burn share must be between " + strconv.FormatInt(minBurnBps, 10) +
 43			" and " + strconv.FormatInt(maxBurnBps, 10) + " bps")
 44	}
 45}
 46func splitPayment(c *Court, spent int64) (burned, reserved int64) {
 47	if c.oneWay {
 48		return spent, 0
 49	}
 50	reserved = mulDiv128(spent, bpsDenom-burnBps, bpsDenom)
 51	return spent - reserved, reserved
 52}
 53func redeemQuote(c *Court, amount int64) (payout, supply int64) {
 54	supply = c.coin.TotalSupply()
 55	if c.oneWay || amount <= 0 || c.reserve <= 0 || supply <= 0 || amount > supply {
 56		return 0, supply
 57	}
 58	return mulDiv128(c.reserve, amount, supply), supply
 59}
 60func mustReturnAMicroGNOT(c *Court, payout, supply int64) {
 61	if payout > 0 {
 62		return
 63	}
 64	least := supply / c.reserve
 65	if supply%c.reserve != 0 {
 66		least++
 67	}
 68	panic("kourtv3: too small to return a µGNOT — redeem at least " + ccAmt(least) + " CC")
 69}
 70func Redeem(cur realm, courtSlug string, amount int64) int64 {
 71	if !cur.IsCurrent() {
 72		panic(errStaleRealm)
 73	}
 74	if amount <= 0 {
 75		panic("kourtv3: redeem amount must be positive")
 76	}
 77	if unsafe.OriginSend().AmountOf(gnotDenom) > 0 {
 78		panic("kourtv3: Redeem takes no GNOT")
 79	}
 80	who := cur.Previous().Address()
 81	c := mustCourt(courtSlug)
 82	if c.oneWay {
 83		panic("kourtv3: this court's coin is one-way; nothing returns GNOT")
 84	}
 85	if who == c.escrow {
 86		panic("kourtv3: the court escrow cannot redeem")
 87	}
 88	touch(c)
 89	if c.reserve <= 0 {
 90		panic("kourtv3: this court holds no reserve")
 91	}
 92	mustSpendable(c, who, amount)
 93	payout, supply := redeemQuote(c, amount)
 94	mustReturnAMicroGNOT(c, payout, supply)
 95	c.coin.Burn(who, amount)
 96	if payout > c.reserve {
 97		panic("kourtv3: reserve accounting")
 98	}
 99	c.reserve -= payout
100	totalReserve -= payout
101	c.redeemedGNOT = mustAdd(c.redeemedGNOT, payout)
102	b := banker.NewBanker(banker.BankerTypeRealmSend, cur)
103	b.SendCoins(cur.Address(), who, chain.Coins{chain.NewCoin(gnotDenom, payout)})
104	chain.Emit(redeemedEvent,
105		"court", c.id,
106		"who", who.String(),
107		"amount", strconv.FormatInt(amount, 10),
108		"ugnot", strconv.FormatInt(payout, 10),
109	)
110	return payout
111}
112func ReserveGNOT(courtSlug string) int64 { return mustCourt(courtSlug).reserve }
113func TotalReserveGNOT() int64 { return totalReserve }
114func RedeemedGNOT(courtSlug string) int64 { return mustCourt(courtSlug).redeemedGNOT }
115func RedeemValue(courtSlug string, amount int64) int64 {
116	p, _ := redeemQuote(mustCourt(courtSlug), amount)
117	return p
118}