royalties.gno
1.60 Kb · 48 lines
1package core
2
3import (
4 "chain"
5 "chain/banker"
6
7 "gno.land/p/g19dzk54hhsdc3gllpksuj6gu4a3e6fl8cr6rn4w/minhwa/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 c := mustCollection(cid)
34 sub := cur.Sub("roy/" + cid)
35 bal := banker.NewReadonlyBanker().GetCoin(sub.Address(), "ugnot")
36 if bal <= 0 {
37 return 0
38 }
39 shares := safe.SplitByBps(bal, c.royaltyPayees)
40 bk := banker.NewBanker(banker.BankerTypeRealmSend, sub)
41 for i, p := range c.royaltyPayees {
42 if shares[i] > 0 {
43 bk.SendCoins(sub.Address(), p.Addr, chain.NewCoins(chain.NewCoin("ugnot", shares[i])))
44 }
45 }
46 chain.Emit("RoyaltiesDistributed", "cid", cid, "amount", itoa(bal))
47 return bal
48}