Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}