Search Apps Documentation Source Content File Folder Download Copy Actions Download

utils.gno

2.81 Kb · 132 lines
  1package personal_world
  2
  3import "gno.land/r/akkadia/v0/admin"
  4
  5func copyStringMap(source map[string]string) map[string]string {
  6	if source == nil {
  7		return nil
  8	}
  9	result := map[string]string{}
 10	for key, value := range source {
 11		result[key] = value
 12	}
 13	return result
 14}
 15
 16func copyStringSlice(source []string) []string {
 17	if source == nil {
 18		return nil
 19	}
 20	result := make([]string, len(source))
 21	for i, value := range source {
 22		result[i] = value
 23	}
 24	return result
 25}
 26
 27const (
 28	maxInt64 = int64(9223372036854775807)
 29)
 30
 31func assertCanGrantRole(worldID uint32, caller address, roleName string) {
 32	if admin.IsAdmin(caller) || isOwner(worldID, caller) {
 33		return
 34	}
 35	if HasPermission(worldID, caller, "role:grant") && hasGrantableRole(worldID, caller, roleName) {
 36		return
 37	}
 38	panic("cannot grant role: caller lacks permission to assign role '" + roleName + "'")
 39}
 40
 41func assertCanRevokeRole(worldID uint32, caller address, roleName string) {
 42	if admin.IsAdmin(caller) || isOwner(worldID, caller) {
 43		return
 44	}
 45	if HasPermission(worldID, caller, "role:revoke") && hasRevokableRole(worldID, caller, roleName) {
 46		return
 47	}
 48	panic("cannot revoke role: caller lacks permission to revoke role '" + roleName + "'")
 49}
 50
 51func parseCSVMap(keys, values string, panicMessagePrefix string) map[string]string {
 52	pending := map[string]string{}
 53	keyStart, valStart := 0, 0
 54	keyIdx, valIdx := 0, 0
 55	for {
 56		for keyIdx < len(keys) && keys[keyIdx] != ',' {
 57			keyIdx++
 58		}
 59		for valIdx < len(values) && values[valIdx] != ',' {
 60			valIdx++
 61		}
 62
 63		key := keys[keyStart:keyIdx]
 64		val := values[valStart:valIdx]
 65		pending[key] = val
 66
 67		keyEnd := keyIdx >= len(keys)
 68		valEnd := valIdx >= len(values)
 69
 70		if keyEnd != valEnd {
 71			panic(panicMessagePrefix + " keys and values count mismatch")
 72		}
 73		if keyEnd {
 74			break
 75		}
 76
 77		keyIdx++
 78		valIdx++
 79		keyStart = keyIdx
 80		valStart = valIdx
 81	}
 82
 83	return pending
 84}
 85
 86func calculateBPSShares(amount int64, bps int64) (int64, int64) {
 87	if amount <= 0 {
 88		return 0, 0
 89	}
 90	denominator := int64(10000)
 91	first := (amount/denominator)*bps + ((amount%denominator)*bps)/denominator
 92	return first, amount - first
 93}
 94
 95func multiplyByBPS(amount int64, bps int64, panicMsg string) int64 {
 96	if amount <= 0 {
 97		return 0
 98	}
 99	if bps < 0 {
100		panic(panicMsg)
101	}
102
103	denominator := int64(10000)
104	wholeAmount := amount / denominator
105	remainingAmount := amount % denominator
106	first := safeMultiply(wholeAmount, bps, panicMsg)
107	second := safeMultiply(remainingAmount, bps, panicMsg) / denominator
108	return safeAdd(first, second, panicMsg)
109}
110
111func safeMultiply(a int64, b int64, panicMsg string) int64 {
112	if a == 0 || b == 0 {
113		return 0
114	}
115	if a < 0 || b < 0 {
116		panic(panicMsg)
117	}
118	if a > maxInt64/b {
119		panic(panicMsg)
120	}
121	return a * b
122}
123
124func safeAdd(a int64, b int64, panicMsg string) int64 {
125	if a < 0 || b < 0 {
126		panic(panicMsg)
127	}
128	if a > maxInt64-b {
129		panic(panicMsg)
130	}
131	return a + b
132}