block_admin.gno
3.44 Kb · 129 lines
1package block
2
3import (
4 "chain"
5
6 "gno.land/p/akkadia/v0/accesscontrol"
7 "gno.land/r/akkadia/v0/admin"
8)
9
10const (
11 CreateSystemBlockEvent = "CreateSystemBlock"
12 AdminDeleteBlockEvent = "AdminDeleteBlock"
13 AdminDeleteSystemBlockEvent = "AdminDeleteSystemBlock"
14 AdminUpdateBlockEvent = "AdminUpdateBlock"
15 SetBlockMetadataEvent = "AdminSetMetadata"
16)
17
18func CreateSystemBlock(cur realm, blockID uint32, propKeys string, propValues string, metadata string) {
19 assertNotFrozen()
20 caller := accesscontrol.MustGetAdminCaller(0, cur, admin.IsAdmin)
21
22 props := parsePropsCSV(propKeys, propValues)
23 createValidator.MustValidate(props)
24 assertBlockName(props["name"])
25 maxSupply := mustParseInt64Field(props, "maxSupply")
26 assertSystemMaxSupply(maxSupply)
27 assertInstallerBPS(mustParseUint32Field(props, "installerBps"))
28 assertMetadata(metadata)
29
30 blockIDStr := blockIDToString(blockID)
31 creator := caller.String()
32 props["creator"] = creator
33 blockStore.CreateSystem(blockID, props)
34 blockStore.SetMetadata(blockID, metadata)
35
36 chain.Emit(
37 CreateSystemBlockEvent,
38 "id", blockIDStr,
39 "name", props["name"],
40 "creator", creator,
41 )
42}
43
44func AdminDeleteBlock(cur realm, blockID uint32) {
45 assertNotFrozen()
46 caller := accesscontrol.MustGetAdminCaller(0, cur, admin.IsAdmin)
47
48 if blockStore.IsSystemID(blockID) {
49 panic("cannot delete system block: " + blockIDToString(blockID))
50 }
51 block := blockStore.MustGet(blockID)
52 assertNoSupply(block)
53
54 blockStore.Delete(blockID)
55 mintedBlockStore.ClearMintAllowlist(blockID)
56
57 chain.Emit(
58 AdminDeleteBlockEvent,
59 "id", blockIDToString(blockID),
60 "caller", caller.String(),
61 )
62}
63
64func AdminDeleteSystemBlock(cur realm, blockID uint32) {
65 assertNotFrozen()
66 caller := accesscontrol.MustGetAdminCaller(0, cur, admin.IsAdmin)
67
68 if !blockStore.IsSystemID(blockID) {
69 panic("not a system block: " + blockIDToString(blockID))
70 }
71 block := blockStore.MustGet(blockID)
72 assertNoSupply(block)
73
74 blockStore.Delete(blockID)
75 mintedBlockStore.ClearMintAllowlist(blockID)
76
77 chain.Emit(
78 AdminDeleteSystemBlockEvent,
79 "id", blockIDToString(blockID),
80 "caller", caller.String(),
81 )
82}
83
84func assertNoSupply(block map[string]string) {
85 blockIDStr := block["id"]
86 blockID := stringToBlockID(blockIDStr)
87 maxSupply := mustParseInt64(block["maxSupply"])
88 // Off-chain blocks (maxSupply == -1) are not minted, so they can bypass the
89 // non-zero supply policy even when they use system block IDs.
90 if maxSupply != -1 && mintedBlockStore.SupplyOf(blockID) != 0 {
91 panic("cannot delete block with non-zero supply: " + blockIDStr)
92 }
93}
94
95func AdminUpdateBlock(cur realm, blockID uint32, propKeys string, propValues string) {
96 assertNotFrozen()
97 accesscontrol.AssertIsAdmin(0, cur, admin.IsAdmin)
98
99 updates := parsePropsCSV(propKeys, propValues)
100 updateValidator.MustValidate(updates)
101 if name, found := updates["name"]; found {
102 assertBlockName(name)
103 }
104 if maxSupply, found := updates["maxSupply"]; found {
105 assertSystemMaxSupply(mustParseInt64(maxSupply))
106 }
107 if installerBPS, found := updates["installerBps"]; found {
108 assertInstallerBPS(mustParseUint32(installerBPS))
109 }
110 blockStore.Update(blockID, updates)
111
112 chain.Emit(
113 AdminUpdateBlockEvent,
114 "id", blockIDToString(blockID),
115 )
116}
117
118func SetBlockMetadata(cur realm, blockID uint32, metadata string) {
119 assertNotFrozen()
120 accesscontrol.AssertIsAdmin(0, cur, admin.IsAdmin)
121 assertMetadata(metadata)
122
123 blockStore.SetMetadata(blockID, metadata)
124
125 chain.Emit(
126 SetBlockMetadataEvent,
127 "id", blockIDToString(blockID),
128 )
129}