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