utils.gno
3.76 Kb · 111 lines
1package pool
2
3import (
4 i256 "gno.land/p/gnoswap/int256"
5 u256 "gno.land/p/gnoswap/uint256"
6 ufmt "gno.land/p/nt/ufmt/v0"
7)
8
9const (
10 MAX_UINT64 string = "18446744073709551615"
11 MAX_INT64 string = "9223372036854775807"
12 MAX_INT128 string = "170141183460469231731687303715884105727"
13 MAX_UINT128 string = "340282366920938463463374607431768211455"
14 MAX_INT256 string = "57896044618658097711785492504343953926634992332820282019728792003956564819967"
15
16 INT64_MIN int64 = -9223372036854775808
17 INT64_MAX int64 = 9223372036854775807
18
19 Q96_RESOLUTION uint = 96
20 Q128_RESOLUTION uint = 128
21
22 Q64 string = "18446744073709551616" // 2 ** 64
23 Q96 string = "79228162514264337593543950336" // 2 ** 96
24 Q128 string = "340282366920938463463374607431768211456" // 2 ** 128
25)
26
27var (
28 maxInt128FromDecimal = i256.MustFromDecimal(MAX_INT128)
29 maxUint128FromDecimal = u256.MustFromDecimal(MAX_UINT128)
30 q128FromDecimal = u256.MustFromDecimal(Q128)
31)
32
33var uint128Mask = func() *u256.Uint {
34 m := u256.Zero().Lsh(u256.One(), Q128_RESOLUTION)
35 return m.Sub(m, u256.One())
36}()
37
38// toUint128 ensures a *u256.Uint value fits within the uint128 range.
39//
40// This function validates that the given `value` is properly initialized and checks whether
41// it exceeds the maximum value of uint128. If the value exceeds the uint128 range,
42// it applies a masking operation to truncate the value to fit within the uint128 limit.
43//
44// Parameters:
45// - value: *u256.Uint, the value to be checked and possibly truncated.
46//
47// Returns:
48// - *u256.Uint: A value guaranteed to fit within the uint128 range.
49//
50// Notes:
51// - The function first checks if the value is not nil to avoid potential runtime errors.
52// - The mask ensures that only the lower 128 bits of the value are retained.
53// - If the input value is already within the uint128 range, it is returned unchanged.
54// - If masking is required, a new instance is returned without modifying the input.
55// - MAX_UINT128 is a constant representing `2^128 - 1`.
56func toUint128(value *u256.Uint) *u256.Uint {
57 if value == nil {
58 panic(newErrorWithDetail(errInvalidInput, "value is nil"))
59 }
60
61 if value.Gt(maxUint128FromDecimal) {
62 return u256.Zero().And(value, uint128Mask)
63 }
64 return value
65}
66
67// u256Min returns the smaller of two *u256.Uint values.
68//
69// This function compares two unsigned 256-bit integers and returns the smaller of the two.
70// If `num1` is less than `num2`, it returns `num1`; otherwise, it returns `num2`.
71//
72// Parameters:
73// - num1 (*u256.Uint): The first unsigned 256-bit integer.
74// - num2 (*u256.Uint): The second unsigned 256-bit integer.
75//
76// Returns:
77// - *u256.Uint: The smaller of `num1` and `num2`.
78//
79// Notes:
80// - This function uses the `Lt` (less than) method of `*u256.Uint` to perform the comparison.
81// - The function assumes both input values are non-nil. If nil inputs are possible in the usage context,
82// additional validation may be needed.
83//
84// Example:
85// smaller := u256Min(u256.MustFromDecimal("10"), u256.MustFromDecimal("20")) // Returns 10
86// smaller := u256Min(u256.MustFromDecimal("30"), u256.MustFromDecimal("20")) // Returns 20
87func u256Min(num1, num2 *u256.Uint) *u256.Uint {
88 if num1.Lt(num2) {
89 return num1
90 }
91 return num2
92}
93
94// checkOverFlowInt128 checks if the value overflows the int128 range.
95func checkOverFlowInt128(value *i256.Int) {
96 if value.Gt(maxInt128FromDecimal) {
97 panic(ufmt.Sprintf(
98 "%v: amount(%s) overflows int128 range",
99 errOverflow, value.ToString()))
100 }
101}
102
103// checkTickSpacing checks if the tick is divisible by the tickSpacing.
104func checkTickSpacing(tick, tickSpacing int32) {
105 if tick%tickSpacing != 0 {
106 panic(newErrorWithDetail(
107 errInvalidTickAndTickSpacing,
108 ufmt.Sprintf("tick(%d) MOD tickSpacing(%d) != 0(%d)", tick, tickSpacing, tick%tickSpacing),
109 ))
110 }
111}