Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}