utils.gno
4.11 Kb · 157 lines
1package v1
2
3import (
4 "math"
5 "strconv"
6 "strings"
7
8 ufmt "gno.land/p/nt/ufmt/v0"
9
10 u256 "gno.land/p/gnoswap/uint256"
11)
12
13const (
14 MAX_INT64 = math.MaxInt64
15 MIN_INT64 = math.MinInt64
16)
17
18func formatBool(value bool) string {
19 if value {
20 return "true"
21 }
22 return "false"
23}
24
25// formatInt returns the string representation of the int64 value.
26func formatInt(value int64) string {
27 return strconv.FormatInt(value, 10)
28}
29
30func buildConditionEventAttrs(conditionTokens string, conditionAmounts string) []string {
31 if conditionTokens == "" {
32 return []string{}
33 }
34
35 tokenPaths := strings.Split(conditionTokens, stringSplitterPad)
36 amounts := strings.Split(conditionAmounts, stringSplitterPad)
37 eventAttrs := make([]string, 0, len(tokenPaths)*2)
38
39 for index, tokenPath := range tokenPaths {
40 eventAttrs = append(eventAttrs, ufmt.Sprintf("conditionsTokens[%d]", index))
41 eventAttrs = append(eventAttrs, tokenPath+stringSplitterPad+amounts[index])
42 }
43
44 return eventAttrs
45}
46
47// parseProjectTierID parses a project tier ID into its project ID and duration.
48// Returns the project ID {tokenPath}:{createdHeight} and the duration of the project tier (30, 90, 180).
49func parseProjectTierID(projectTierID string) (string, int64) {
50 parts := strings.Split(projectTierID, ":")
51 if len(parts) != 3 {
52 panic(makeErrorWithDetails(
53 errInvalidData,
54 ufmt.Sprintf("(%s)", projectTierID),
55 ))
56 }
57
58 projectID := parts[0] + ":" + parts[1]
59
60 tierDuration, err := strconv.ParseInt(parts[2], 10, 64)
61 if err != nil {
62 panic(makeErrorWithDetails(
63 errInvalidData,
64 ufmt.Sprintf("(%s)", projectTierID),
65 ))
66 }
67
68 // Validate tier duration
69 if tierDuration != projectTier30 && tierDuration != projectTier90 && tierDuration != projectTier180 {
70 panic(makeErrorWithDetails(
71 errInvalidTier,
72 ufmt.Sprintf("pool type(%d) is not available", tierDuration),
73 ))
74 }
75
76 return projectID, tierDuration
77}
78
79// safeConvertToInt64 safely converts a *u256.Uint value to an int64, ensuring no overflow.
80//
81// This function attempts to convert the given *u256.Uint value to an int64. If the value exceeds
82// the maximum allowable range for int64 (`2^63 - 1`), it triggers a panic with a descriptive error message.
83//
84// Parameters:
85// - value (*u256.Uint): The unsigned 256-bit integer to be converted.
86//
87// Returns:
88// - int64: The converted value if it falls within the int64 range.
89//
90// Panics:
91// - If the `value` exceeds the range of int64, the function will panic with an error indicating
92// the overflow and the original value.
93func safeConvertToInt64(value *u256.Uint) int64 {
94 res, overflow := value.Uint64WithOverflow()
95 if overflow || res > uint64(MAX_INT64) {
96 panic(ufmt.Sprintf(
97 "amount(%s) overflows int64 range (max 9223372036854775807)",
98 value.ToString(),
99 ))
100 }
101 return int64(res)
102}
103
104// safeAddInt64 performs safe addition of int64 values, panicking on overflow or underflow
105func safeAddInt64(a, b int64) int64 {
106 if a > 0 && b > MAX_INT64-a {
107 panic("int64 addition overflow")
108 }
109
110 if a < 0 && b < MIN_INT64-a {
111 panic("int64 addition underflow")
112 }
113
114 return a + b
115}
116
117// safeSubInt64 performs safe subtraction of int64 values, panicking on overflow or underflow
118func safeSubInt64(a, b int64) int64 {
119 if b > 0 && a < MIN_INT64+b {
120 panic("int64 subtraction underflow")
121 }
122
123 if b < 0 && a > MAX_INT64+b {
124 panic("int64 subtraction overflow")
125 }
126
127 return a - b
128}
129
130// safeMulDiv performs safe multiplication and division: (a * b) / c
131// Prevents overflow in multiplication step by checking bounds
132func safeMulDiv(a, b, c int64) int64 {
133 if c == 0 {
134 panic("division by zero in safeMulDiv")
135 }
136
137 // Check for multiplication overflow
138 // If a * b would overflow, we need to be careful
139 if a != 0 && b != 0 {
140 // Check if multiplication would overflow
141 if a > 0 && b > 0 && a > MAX_INT64/b {
142 panic("int64 multiplication overflow in safeMulDiv")
143 }
144 if a > 0 && b < 0 && b < MIN_INT64/a {
145 panic("int64 multiplication underflow in safeMulDiv")
146 }
147 if a < 0 && b > 0 && a < MIN_INT64/b {
148 panic("int64 multiplication underflow in safeMulDiv")
149 }
150 if a < 0 && b < 0 && a < MAX_INT64/b {
151 panic("int64 multiplication overflow in safeMulDiv")
152 }
153 }
154
155 result := (a * b) / c
156 return result
157}