github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/accounts/abi/argument.go (about) 1 package abi 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strings" 8 ) 9 10 type Argument struct { 11 Name string 12 Type Type 13 Indexed bool 14 } 15 16 type Arguments []Argument 17 18 type ArgumentMarshaling struct { 19 Name string 20 Type string 21 InternalType string 22 Components []ArgumentMarshaling 23 Indexed bool 24 } 25 26 func (argument *Argument) UnmarshalJSON(data []byte) error { 27 var arg ArgumentMarshaling 28 err := json.Unmarshal(data, &arg) 29 if err != nil { 30 return fmt.Errorf("argument json err: %v", err) 31 } 32 33 argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components) 34 if err != nil { 35 return err 36 } 37 argument.Name = arg.Name 38 argument.Indexed = arg.Indexed 39 40 return nil 41 } 42 43 func (arguments Arguments) LengthNonIndexed() int { 44 out := 0 45 for _, arg := range arguments { 46 if !arg.Indexed { 47 out++ 48 } 49 } 50 return out 51 } 52 53 func (arguments Arguments) NonIndexed() Arguments { 54 var ret []Argument 55 for _, arg := range arguments { 56 if !arg.Indexed { 57 ret = append(ret, arg) 58 } 59 } 60 return ret 61 } 62 63 func (arguments Arguments) isTuple() bool { 64 return len(arguments) > 1 65 } 66 67 func (arguments Arguments) Unpack(v interface{}, data []byte) error { 68 if len(data) == 0 { 69 if len(arguments) != 0 { 70 return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 71 } else { 72 return nil 73 } 74 } 75 if reflect.Ptr != reflect.ValueOf(v).Kind() { 76 return fmt.Errorf("abi: Unpack(non-pointer %T)", v) 77 } 78 marshalledValues, err := arguments.UnpackValues(data) 79 if err != nil { 80 return err 81 } 82 if arguments.isTuple() { 83 return arguments.unpackTuple(v, marshalledValues) 84 } 85 return arguments.unpackAtomic(v, marshalledValues[0]) 86 } 87 88 func (arguments Arguments) UnpackForRevert(v interface{}, data []byte) ([]interface{}, error) { 89 if len(data) == 0 { 90 if len(arguments) != 0 { 91 return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 92 } else { 93 return nil, nil 94 } 95 } 96 if reflect.Ptr != reflect.ValueOf(v).Kind() { 97 return nil, fmt.Errorf("abi: Unpack(non-pointer %T)", v) 98 } 99 return arguments.UnpackValues(data) 100 } 101 102 func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { 103 if len(data) == 0 { 104 if len(arguments) != 0 { 105 return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 106 } else { 107 return nil 108 } 109 } 110 marshalledValues, err := arguments.UnpackValues(data) 111 if err != nil { 112 return err 113 } 114 return arguments.unpackIntoMap(v, marshalledValues) 115 } 116 117 func unpack(t *Type, dst interface{}, src interface{}) error { 118 var ( 119 dstVal = reflect.ValueOf(dst).Elem() 120 srcVal = reflect.ValueOf(src) 121 ) 122 tuple, typ := false, t 123 for { 124 if typ.T == SliceTy || typ.T == ArrayTy { 125 typ = typ.Elem 126 continue 127 } 128 tuple = typ.T == TupleTy 129 break 130 } 131 if !tuple { 132 return set(dstVal, srcVal) 133 } 134 135 dstVal = indirectInterfaceOrPtr(dstVal) 136 137 switch t.T { 138 case TupleTy: 139 if dstVal.Kind() != reflect.Struct { 140 return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind()) 141 } 142 fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal) 143 if err != nil { 144 return err 145 } 146 for i, elem := range t.TupleElems { 147 fname := fieldmap[t.TupleRawNames[i]] 148 field := dstVal.FieldByName(fname) 149 if !field.IsValid() { 150 return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i]) 151 } 152 if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil { 153 return err 154 } 155 } 156 return nil 157 case SliceTy: 158 if dstVal.Kind() != reflect.Slice { 159 return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind()) 160 } 161 slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len()) 162 for i := 0; i < slice.Len(); i++ { 163 if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { 164 return err 165 } 166 } 167 dstVal.Set(slice) 168 case ArrayTy: 169 if dstVal.Kind() != reflect.Array { 170 return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind()) 171 } 172 array := reflect.New(dstVal.Type()).Elem() 173 for i := 0; i < array.Len(); i++ { 174 if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { 175 return err 176 } 177 } 178 dstVal.Set(array) 179 } 180 return nil 181 } 182 183 func (arguments Arguments) unpackIntoMap(v map[string]interface{}, marshalledValues []interface{}) error { 184 185 if v == nil { 186 return fmt.Errorf("abi: cannot unpack into a nil map") 187 } 188 189 for i, arg := range arguments.NonIndexed() { 190 v[arg.Name] = marshalledValues[i] 191 } 192 return nil 193 } 194 195 func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { 196 if arguments.LengthNonIndexed() == 0 { 197 return nil 198 } 199 argument := arguments.NonIndexed()[0] 200 elem := reflect.ValueOf(v).Elem() 201 202 if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy { 203 fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem) 204 if err != nil { 205 return err 206 } 207 field := elem.FieldByName(fieldmap[argument.Name]) 208 if !field.IsValid() { 209 return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name) 210 } 211 return unpack(&argument.Type, field.Addr().Interface(), marshalledValues) 212 } 213 return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues) 214 } 215 216 func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { 217 var ( 218 value = reflect.ValueOf(v).Elem() 219 typ = value.Type() 220 kind = value.Kind() 221 ) 222 if err := requireUnpackKind(value, typ, kind, arguments); err != nil { 223 return err 224 } 225 226 var abi2struct map[string]string 227 if kind == reflect.Struct { 228 var ( 229 argNames []string 230 err error 231 ) 232 for _, arg := range arguments.NonIndexed() { 233 argNames = append(argNames, arg.Name) 234 } 235 abi2struct, err = mapArgNamesToStructFields(argNames, value) 236 if err != nil { 237 return err 238 } 239 } 240 for i, arg := range arguments.NonIndexed() { 241 switch kind { 242 case reflect.Struct: 243 field := value.FieldByName(abi2struct[arg.Name]) 244 if !field.IsValid() { 245 return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name) 246 } 247 if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil { 248 return err 249 } 250 case reflect.Slice, reflect.Array: 251 if value.Len() < i { 252 return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) 253 } 254 v := value.Index(i) 255 if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil { 256 return err 257 } 258 if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil { 259 return err 260 } 261 default: 262 return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ) 263 } 264 } 265 return nil 266 267 } 268 269 func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { 270 retval := make([]interface{}, 0, arguments.LengthNonIndexed()) 271 virtualArgs := 0 272 for index, arg := range arguments.NonIndexed() { 273 marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) 274 if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) { 275 virtualArgs += getTypeSize(arg.Type)/32 - 1 276 } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) { 277 virtualArgs += getTypeSize(arg.Type)/32 - 1 278 } 279 if err != nil { 280 return nil, err 281 } 282 retval = append(retval, marshalledValue) 283 } 284 return retval, nil 285 } 286 287 func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { 288 return arguments.Pack(args...) 289 } 290 291 func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { 292 abiArgs := arguments 293 if len(args) != len(abiArgs) { 294 return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs)) 295 } 296 var variableInput []byte 297 298 inputOffset := 0 299 for _, abiArg := range abiArgs { 300 inputOffset += getTypeSize(abiArg.Type) 301 } 302 var ret []byte 303 for i, a := range args { 304 input := abiArgs[i] 305 packed, err := input.Type.pack(reflect.ValueOf(a)) 306 if err != nil { 307 return nil, err 308 } 309 if isDynamicType(input.Type) { 310 ret = append(ret, packNum(reflect.ValueOf(inputOffset))...) 311 inputOffset += len(packed) 312 variableInput = append(variableInput, packed...) 313 } else { 314 ret = append(ret, packed...) 315 } 316 } 317 ret = append(ret, variableInput...) 318 319 return ret, nil 320 } 321 322 func ToCamelCase(input string) string { 323 parts := strings.Split(input, "_") 324 for i, s := range parts { 325 if len(s) > 0 { 326 parts[i] = strings.ToUpper(s[:1]) + s[1:] 327 } 328 } 329 return strings.Join(parts, "") 330 }