Search Apps Documentation Source Content File Folder Download Copy Actions Download

utils.gno

5.60 Kb · 197 lines
  1package v1
  2
  3import (
  4	"math"
  5	"strconv"
  6	"strings"
  7
  8	"gno.land/p/gnoswap/deps/grc721"
  9	prabc "gno.land/p/gnoswap/rbac"
 10	u256 "gno.land/p/gnoswap/uint256"
 11	ufmt "gno.land/p/nt/ufmt/v0"
 12	"gno.land/r/gnoswap/access"
 13)
 14
 15const MAX_UINT256 string = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
 16
 17func mustGetStakerAddress() address {
 18	return access.MustGetAddress(prabc.ROLE_STAKER.String())
 19}
 20
 21// positionIdFrom converts positionId to grc721.TokenID type
 22// input: positionId uint64
 23// output: grc721.TokenID
 24func positionIdFrom(positionId uint64) grc721.TokenID {
 25	return grc721.TokenID(strconv.FormatUint(positionId, 10))
 26}
 27
 28// exists checks whether positionId exists
 29// If positionId doesn't exist, return false, otherwise return true
 30// input: positionId uint64
 31// output: bool
 32func (p *positionV1) exists(positionId uint64) bool {
 33	return p.nftAccessor.Exists(positionIdFrom(positionId))
 34}
 35
 36// isOwner checks whether the caller is the owner of the positionId
 37// If the caller is the owner of the positionId, return true, otherwise return false
 38// input: positionId uint64, addr std.Address
 39// output: bool
 40func (p *positionV1) isOwner(positionId uint64, addr address) bool {
 41	owner, err := p.nftAccessor.OwnerOf(positionIdFrom(positionId))
 42	if err != nil {
 43		return false
 44	}
 45	return owner == addr
 46}
 47
 48// isOperator checks whether the caller is the approved operator of the positionId
 49// If the caller is the approved operator of the positionId, return true, otherwise return false
 50// input: positionId uint64, addr std.Address
 51// output: bool
 52func (p *positionV1) isOperator(positionId uint64, addr address) bool {
 53	return p.GetPositionOperator(positionId) == addr
 54}
 55
 56// isStaked checks whether positionId is staked
 57// If positionId is staked, owner of positionId is staker contract
 58// If positionId is staked, return true, otherwise return false
 59// input: positionId grc721.TokenID
 60// output: bool
 61func (p *positionV1) isStaked(positionId grc721.TokenID) bool {
 62	exist := p.nftAccessor.Exists(positionId)
 63	if !exist {
 64		return false
 65	}
 66	owner, err := p.nftAccessor.OwnerOf(positionId)
 67	if err == nil && owner == mustGetStakerAddress() {
 68		return true
 69	}
 70	return false
 71}
 72
 73// isOwnerOrOperator checks whether the caller is the owner or approved operator of the positionId
 74// If the caller is the owner or approved operator of the positionId, return true, otherwise return false
 75// input: addr std.Address, positionId uint64
 76// output: bool
 77func (p *positionV1) isOwnerOrOperator(positionId uint64, addr address) bool {
 78	if !addr.IsValid() || !p.exists(positionId) {
 79		return false
 80	}
 81
 82	if p.isStaked(positionIdFrom(positionId)) {
 83		return p.isOperator(positionId, addr)
 84	}
 85
 86	return p.isOwner(positionId, addr)
 87}
 88
 89// splitOf divides poolKey into pToken0, pToken1, and pFee
 90// If poolKey is invalid, it will panic
 91//
 92// input: poolKey string
 93// output:
 94// - token0Path string
 95// - token1Path string
 96// - fee uint32
 97func splitOf(poolKey string) (string, string, uint32) {
 98	res := strings.Split(poolKey, ":")
 99	if len(res) != 3 {
100		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid poolKey(%s)", poolKey)))
101	}
102
103	pToken0, pToken1, pFeeStr := res[0], res[1], res[2]
104
105	pFee, err := strconv.Atoi(pFeeStr)
106	if err != nil {
107		panic(newErrorWithDetail(errInvalidInput, ufmt.Sprintf("invalid fee(%s)", pFeeStr)))
108	}
109
110	return pToken0, pToken1, uint32(pFee)
111}
112
113func formatUint(v any) string {
114	switch v := v.(type) {
115	case uint8:
116		return strconv.FormatUint(uint64(v), 10)
117	case uint32:
118		return strconv.FormatUint(uint64(v), 10)
119	case uint64:
120		return strconv.FormatUint(v, 10)
121	default:
122		panic(ufmt.Sprintf("invalid type: %T", v))
123	}
124}
125
126func formatInt(v any) string {
127	switch v := v.(type) {
128	case int32:
129		return strconv.FormatInt(int64(v), 10)
130	case int64:
131		return strconv.FormatInt(v, 10)
132	case int:
133		return strconv.Itoa(v)
134	default:
135		panic(ufmt.Sprintf("invalid type: %T", v))
136	}
137}
138
139func isSlippageExceeded(amount0, amount1, amount0Min, amount1Min *u256.Uint) bool {
140	return !(amount0.Gte(amount0Min) && amount1.Gte(amount1Min))
141}
142
143// safeConvertToInt64 safely converts a *u256.Uint value to an int64, ensuring no overflow.
144//
145// This function attempts to convert the given *u256.Uint value to an int64. If the value exceeds
146// the maximum allowable range for int64 (`2^63 - 1`), it triggers a panic with a descriptive error message.
147//
148// Parameters:
149// - value (*u256.Uint): The unsigned 256-bit integer to be converted.
150//
151// Returns:
152// - int64: The converted value if it falls within the int64 range.
153//
154// Panics:
155//   - If the `value` exceeds the range of int64, the function will panic with an error indicating
156//     the overflow and the original value.
157func safeConvertToInt64(value *u256.Uint) int64 {
158	res, overflow := value.Uint64WithOverflow()
159	if overflow || res > 9223372036854775807 {
160		panic(ufmt.Sprintf(
161			"amount(%s) overflows int64 range (max: 9223372036854775807)",
162			value.ToString(),
163		))
164	}
165	return int64(res)
166}
167
168func safeParseInt64(value string) int64 {
169	amountInt64, err := strconv.ParseInt(value, 10, 64)
170	if err != nil {
171		panic(err)
172	}
173
174	return amountInt64
175}
176
177// safeAddInt64 performs safe addition of int64 values, panicking on overflow or underflow.
178func safeAddInt64(a, b int64) int64 {
179	if a > 0 && b > math.MaxInt64-a {
180		panic("int64 addition overflow")
181	}
182	if a < 0 && b < math.MinInt64-a {
183		panic("int64 addition underflow")
184	}
185	return a + b
186}
187
188// safeSubInt64 performs safe subtraction of int64 values, panicking on overflow or underflow.
189func safeSubInt64(a, b int64) int64 {
190	if b > 0 && a < math.MinInt64+b {
191		panic("int64 subtraction underflow")
192	}
193	if b < 0 && a > math.MaxInt64+b {
194		panic("int64 subtraction overflow")
195	}
196	return a - b
197}