github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/pack.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2016 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package abi 28 29 import ( 30 "errors" 31 "fmt" 32 "math/big" 33 "reflect" 34 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/common/math" 37 ) 38 39 // packBytesSlice packs the given bytes as [L, V] as the canonical representation 40 // bytes slice. 41 func packBytesSlice(bytes []byte, l int) []byte { 42 len := packNum(reflect.ValueOf(l)) 43 return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...) 44 } 45 46 // packElement packs the given reflect value according to the abi specification in 47 // t. 48 func packElement(t Type, reflectValue reflect.Value) ([]byte, error) { 49 switch t.T { 50 case IntTy, UintTy: 51 return packNum(reflectValue), nil 52 case StringTy: 53 return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil 54 case AddressTy: 55 if reflectValue.Kind() == reflect.Array { 56 reflectValue = mustArrayToByteSlice(reflectValue) 57 } 58 59 return common.LeftPadBytes(reflectValue.Bytes(), 32), nil 60 case BoolTy: 61 if reflectValue.Bool() { 62 return math.PaddedBigBytes(common.Big1, 32), nil 63 } 64 return math.PaddedBigBytes(common.Big0, 32), nil 65 case BytesTy: 66 if reflectValue.Kind() == reflect.Array { 67 reflectValue = mustArrayToByteSlice(reflectValue) 68 } 69 if reflectValue.Type() != reflect.TypeOf([]byte{}) { 70 return []byte{}, errors.New("Bytes type is neither slice nor array") 71 } 72 return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil 73 case FixedBytesTy, FunctionTy: 74 if reflectValue.Kind() == reflect.Array { 75 reflectValue = mustArrayToByteSlice(reflectValue) 76 } 77 return common.RightPadBytes(reflectValue.Bytes(), 32), nil 78 default: 79 return []byte{}, fmt.Errorf("Could not pack element, unknown type: %v", t.T) 80 } 81 } 82 83 // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation. 84 func packNum(value reflect.Value) []byte { 85 switch kind := value.Kind(); kind { 86 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 87 return math.U256Bytes(new(big.Int).SetUint64(value.Uint())) 88 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 89 return math.U256Bytes(big.NewInt(value.Int())) 90 case reflect.Ptr: 91 return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int))) 92 default: 93 panic("abi: fatal error") 94 } 95 }