buy.gno
2.12 Kb · 67 lines
1package kourtv3
2import (
3 "chain"
4 "chain/banker"
5 "chain/runtime/unsafe"
6 "strconv"
7)
8const gnotDenom = "ugnot"
9const burnSinkPath = "gno.land/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/kourtv3:burned"
10func Buy(cur realm, slug string, minUnits int64) int64 {
11 if !cur.IsCurrent() {
12 panic(errStaleRealm)
13 }
14 prev := cur.Previous()
15 if !prev.IsUserCall() {
16 panic("kourtv3: a buy must be a direct user call")
17 }
18 buyer := prev.Address()
19 c := mustCourt(slug)
20 if buyer == cur.Address() {
21 panic("kourtv3: the court's own address may not buy")
22 }
23 touch(c)
24 sent := unsafe.OriginSend().AmountOf(gnotDenom)
25 if sent <= 0 {
26 panic("kourtv3: send GNOT to buy the coin")
27 }
28 delta, spent := c.crv.Minted(c.minted, sent)
29 if delta <= 0 {
30 panic("kourtv3: payment too small to mint a coin")
31 }
32 if delta < minUnits {
33 panic("kourtv3: this offering would mint fewer units than your floor — " +
34 strconv.FormatInt(delta, 10) + " < " + strconv.FormatInt(minUnits, 10))
35 }
36 c.minted += delta
37 recordPrice(c)
38 c.coin.Mint(buyer, delta)
39 burned, reserved := splitPayment(c, spent)
40 c.reserve = mustAdd(c.reserve, reserved)
41 c.paidIn = mustAdd(c.paidIn, spent)
42 totalReserve = mustAdd(totalReserve, reserved)
43 reindexBurn(c, burned)
44 accrueFranchise(c, buyer, burned)
45 b := banker.NewBanker(banker.BankerTypeRealmSend, cur)
46 b.SendCoins(cur.Address(), chain.PackageAddress(burnSinkPath),
47 chain.Coins{chain.NewCoin(gnotDenom, burned)})
48 if r := sent - spent; r > 0 {
49 b.SendCoins(cur.Address(), buyer, chain.Coins{chain.NewCoin(gnotDenom, r)})
50 }
51 chain.Emit(boughtEvent,
52 "court", c.id,
53 "who", buyer.String(),
54 "minted", strconv.FormatInt(delta, 10),
55 "spent", strconv.FormatInt(spent, 10),
56 "burned", strconv.FormatInt(burned, 10),
57 "reserved", strconv.FormatInt(reserved, 10),
58 )
59 return delta
60}
61func CurvePosition(slug string) int64 { return mustCourt(slug).minted }
62func BurnSink() address { return chain.PackageAddress(burnSinkPath) }
63func BurnedGNOT() int64 {
64 b := banker.NewReadonlyBanker()
65 return b.GetCoin(chain.PackageAddress(burnSinkPath), gnotDenom)
66}
67func CoinBalanceOf(slug string, who address) int64 { return mustCourt(slug).coin.BalanceOf(who) }