validation.gno
3.39 Kb · 145 lines
1package block
2
3import (
4 "strconv"
5 "strings"
6 "unicode/utf8"
7
8 "gno.land/p/g1nqnrt3aldzhu6zzeg75yw97wvavqy7wr77g56q/deploy-test/v2/validate"
9)
10
11const maxBlockNameLength = 30
12
13// Validation helpers in this file are for value-level checks at public API boundaries.
14//
15// Add helpers here when they validate a parameter or payload value without
16// depending on mutable contract state or call flow. Store-owned existence,
17// duplicate, and index consistency checks stay in the relevant store.
18func assertBlockName(name string) {
19 if name == "" {
20 panic("name cannot be empty")
21 }
22 if utf8.RuneCountInString(name) > maxBlockNameLength {
23 panic("name too long (max 30)")
24 }
25 trimmed := strings.TrimSpace(name)
26 if trimmed == "" {
27 panic("name cannot be only whitespace")
28 }
29 if name != trimmed {
30 panic("name cannot have leading or trailing whitespace")
31 }
32 for i := 0; i < len(name); i++ {
33 switch name[i] {
34 case ',', '|', '/', '\\', '<', '>', '[', ']', '(', ')', '{', '}', '#', '*', '`':
35 panic("name contains invalid characters")
36 }
37 if name[i] < 0x20 || name[i] == 0x7f {
38 panic("name contains invalid characters")
39 }
40 }
41}
42
43func assertNormalMaxSupply(maxSupply uint32) {
44 if maxSupply == 0 {
45 panic("max supply must be greater than 0")
46 }
47}
48
49func assertSystemMaxSupply(maxSupply int64) {
50 if maxSupply < -1 {
51 panic("max supply must be greater than -2")
52 }
53}
54
55func assertInstallerBPS(installerBPS uint32) {
56 if installerBPS > 10000 {
57 panic("installer bps must be between 0 and 10000")
58 }
59}
60
61func assertMetadata(metadata string) {
62 validate.AssertStringTextLen(metadata, true, "block metadata")
63}
64
65func assertExactPayment(expected int64, actual int64) {
66 if actual != expected {
67 panic("exact payment required: expected " + strconv.FormatInt(expected, 10) + ", got " + strconv.FormatInt(actual, 10))
68 }
69}
70
71func mustParseUint32Field(props map[string]string, key string) uint32 {
72 return mustParseUint32(props[key])
73}
74
75func mustParseInt64Field(props map[string]string, key string) int64 {
76 return mustParseInt64(props[key])
77}
78
79func mustParseUint32(val string) uint32 {
80 value, err := strconv.ParseUint(val, 10, 32)
81 if err != nil {
82 panic("invalid uint32: " + err.Error())
83 }
84 return uint32(value)
85}
86
87func mustParseUint8(val string) uint8 {
88 value, err := strconv.ParseUint(val, 10, 8)
89 if err != nil {
90 panic("invalid uint8: " + err.Error())
91 }
92 return uint8(value)
93}
94
95func mustParseInt64(val string) int64 {
96 value, err := strconv.ParseInt(val, 10, 64)
97 if err != nil {
98 panic("invalid int64: " + err.Error())
99 }
100 return value
101}
102
103func mustParseAddress(str string) address {
104 addr := address(str)
105 if !addr.IsValid() {
106 panic("invalid address: " + str)
107 }
108 return addr
109}
110
111func assertListPageCount(page int, count int) {
112 if page < 1 {
113 panic("page must be at least 1")
114 }
115 if count < 1 {
116 panic("count must be at least 1")
117 }
118 assertListLimit("count", count)
119}
120
121func assertListLimit(field string, count int) {
122 if count > listLimit {
123 panic(field + " exceeds listLimit (max: " + strconv.Itoa(listLimit) + ")")
124 }
125}
126
127func parseMintAllowlistCSV(minters string) []address {
128 if minters == "" {
129 panic("minters must not be empty")
130 }
131
132 result := []address{}
133 start := 0
134 for i := 0; i <= len(minters); i++ {
135 if i == len(minters) || minters[i] == ',' {
136 addr := strings.TrimSpace(minters[start:i])
137 if addr == "" {
138 panic("empty address not allowed")
139 }
140 result = append(result, mustParseAddress(addr))
141 start = i + 1
142 }
143 }
144 return result
145}