marketplace.gno
2.26 Kb · 70 lines
1package guardians
2
3import (
4 "chain"
5
6 "gno.land/p/nt/avl/v0"
7 "gno.land/p/nt/grc721/v0"
8 "gno.land/p/nt/ufmt/v0"
9)
10
11var (
12 authorizedMarketplace address
13 settledMarketNonces avl.Tree
14)
15
16func AuthorizedMarketplace() address { return authorizedMarketplace }
17
18// SetAuthorizedMarketplace is a one-time binding made before minting. Keeping
19// the PrivateLedger and Token handle private prevents other approved operators
20// from bypassing the official royalty settlement path.
21func SetAuthorizedMarketplace(cur realm, marketplace address) {
22 assertAdmin(cur.Previous().Address())
23 if authorizedMarketplace.IsValid() {
24 panic("guardians: authorized marketplace is locked")
25 }
26 if !marketplace.IsValid() {
27 panic("guardians: invalid marketplace address")
28 }
29 if token.TotalSupply() != 0 || !salePaused {
30 panic("guardians: configure marketplace before minting and sale activation")
31 }
32 authorizedMarketplace = marketplace
33 chain.Emit("MarketplaceAuthorized", "marketplace", marketplace.String())
34}
35
36// MarketplaceTransfer is the only operator-transfer route. The authorized
37// market supplies its consumed listing nonce and gross price for audit events.
38func MarketplaceTransfer(cur realm, seller, buyer address, tokenID string, grossPrice, nonce int64) {
39 marketplace := cur.Previous().Address()
40 if marketplace != authorizedMarketplace || !authorizedMarketplace.IsValid() {
41 panic("guardians: caller is not authorized marketplace")
42 }
43 if grossPrice < 1 || nonce < 1 {
44 panic("guardians: invalid marketplace settlement")
45 }
46 nonceKey := marketplace.String() + ":" + ufmt.Sprintf("%d", nonce)
47 if settledMarketNonces.Has(nonceKey) {
48 panic("guardians: marketplace nonce already settled")
49 }
50 if OwnerOf(tokenID) != seller {
51 panic("guardians: marketplace seller is not token owner")
52 }
53 if !token.IsApprovedForAll(seller, marketplace) {
54 panic("guardians: marketplace operator approval required")
55 }
56
57 settledMarketNonces.Set(nonceKey, true)
58 if err := ledger.TransferFrom(marketplace, seller, buyer, grc721.TokenID(tokenID)); err != nil {
59 panic(err)
60 }
61 chain.Emit(
62 "MarketplaceSettlementTransfer",
63 "marketplace", marketplace.String(),
64 "tokenId", tokenID,
65 "seller", seller.String(),
66 "buyer", buyer.String(),
67 "grossPrice", ufmt.Sprintf("%d", grossPrice),
68 "nonce", ufmt.Sprintf("%d", nonce),
69 )
70}