royalties.gno
1.68 Kb · 52 lines
1package core
2
3import (
4 "chain"
5 "chain/banker"
6
7 "gno.land/p/g1pq6pxhgxk2uw5shg5le6glfydpxcu74k0zh069/sinopia/safe/v1"
8)
9
10// Each collection's royalty receiver is its own sub-treasury
11// DerivePkgSubAddr(core, "roy/<cid>"), written into the official royalty
12// extension at creation. Any market can pay it through RoyaltyInfo; the
13// creator can re-split it later (SetPayees) without touching the receiver.
14// Only core can spend it: a banker for a sub-address needs core's live
15// cur.Sub (interrealm v2 §5.5).
16
17func royaltyAddress(cid string) address {
18 return chain.DerivePkgSubAddr(selfPath, "roy/"+cid)
19}
20
21// RoyaltyAddress is the collection's royalty sub-treasury.
22func RoyaltyAddress(cid string) address {
23 mustCollection(cid)
24 return royaltyAddress(cid)
25}
26
27// DistributeRoyalties pushes the whole sub-treasury balance to the royalty
28// payees. Permissionless and never paused (I-2); market/v1 calls it after
29// every sale. Returns the amount distributed. The sub-realm banker spend
30// is verified by spike/subtoken, core and market tests on gno v1.7.0.
31func DistributeRoyalties(cur realm, cid string) int64 {
32 assertNoDeposit(cur)
33 return distribute(cur, mustCollection(cid))
34}
35
36func distribute(cur realm, c *collection) int64 {
37 cid := c.id
38 sub := cur.Sub("roy/" + cid)
39 bal := banker.NewReadonlyBanker().GetCoin(sub.Address(), "ugnot")
40 if bal <= 0 {
41 return 0
42 }
43 shares := safe.SplitByBps(bal, c.royaltyPayees)
44 bk := banker.NewBanker(banker.BankerTypeRealmSend, sub)
45 for i, p := range c.royaltyPayees {
46 if shares[i] > 0 {
47 bk.SendCoins(sub.Address(), p.Addr, chain.NewCoins(chain.NewCoin("ugnot", shares[i])))
48 }
49 }
50 chain.Emit("RoyaltiesDistributed", "cid", cid, "amount", itoa(bal))
51 return bal
52}