github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/accounts/abi/bind/topics.go (about) 1 package bind 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 "math/big" 8 "reflect" 9 10 "github.com/neatio-net/neatio/chain/accounts/abi" 11 "github.com/neatio-net/neatio/utilities/common" 12 "github.com/neatio-net/neatio/utilities/crypto" 13 ) 14 15 func makeTopics(query ...[]interface{}) ([][]common.Hash, error) { 16 topics := make([][]common.Hash, len(query)) 17 for i, filter := range query { 18 for _, rule := range filter { 19 var topic common.Hash 20 21 switch rule := rule.(type) { 22 case common.Hash: 23 copy(topic[:], rule[:]) 24 case common.Address: 25 copy(topic[common.HashLength-common.AddressLength:], rule[:]) 26 case *big.Int: 27 blob := rule.Bytes() 28 copy(topic[common.HashLength-len(blob):], blob) 29 case bool: 30 if rule { 31 topic[common.HashLength-1] = 1 32 } 33 case int8: 34 blob := big.NewInt(int64(rule)).Bytes() 35 copy(topic[common.HashLength-len(blob):], blob) 36 case int16: 37 blob := big.NewInt(int64(rule)).Bytes() 38 copy(topic[common.HashLength-len(blob):], blob) 39 case int32: 40 blob := big.NewInt(int64(rule)).Bytes() 41 copy(topic[common.HashLength-len(blob):], blob) 42 case int64: 43 blob := big.NewInt(rule).Bytes() 44 copy(topic[common.HashLength-len(blob):], blob) 45 case uint8: 46 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 47 copy(topic[common.HashLength-len(blob):], blob) 48 case uint16: 49 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 50 copy(topic[common.HashLength-len(blob):], blob) 51 case uint32: 52 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 53 copy(topic[common.HashLength-len(blob):], blob) 54 case uint64: 55 blob := new(big.Int).SetUint64(rule).Bytes() 56 copy(topic[common.HashLength-len(blob):], blob) 57 case string: 58 hash := crypto.Keccak256Hash([]byte(rule)) 59 copy(topic[:], hash[:]) 60 case []byte: 61 hash := crypto.Keccak256Hash(rule) 62 copy(topic[:], hash[:]) 63 64 default: 65 66 val := reflect.ValueOf(rule) 67 switch { 68 69 case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: 70 reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val) 71 default: 72 return nil, fmt.Errorf("unsupported indexed type: %T", rule) 73 } 74 } 75 topics[i] = append(topics[i], topic) 76 } 77 } 78 return topics, nil 79 } 80 81 var ( 82 reflectHash = reflect.TypeOf(common.Hash{}) 83 reflectAddress = reflect.TypeOf(common.Address{}) 84 reflectBigInt = reflect.TypeOf(new(big.Int)) 85 ) 86 87 func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) error { 88 89 if len(fields) != len(topics) { 90 return errors.New("topic/field count mismatch") 91 } 92 93 for _, arg := range fields { 94 if !arg.Indexed { 95 return errors.New("non-indexed field in topic reconstruction") 96 } 97 field := reflect.ValueOf(out).Elem().FieldByName(capitalise(arg.Name)) 98 99 switch field.Kind() { 100 case reflect.Bool: 101 if topics[0][common.HashLength-1] == 1 { 102 field.Set(reflect.ValueOf(true)) 103 } 104 case reflect.Int8: 105 num := new(big.Int).SetBytes(topics[0][:]) 106 field.Set(reflect.ValueOf(int8(num.Int64()))) 107 108 case reflect.Int16: 109 num := new(big.Int).SetBytes(topics[0][:]) 110 field.Set(reflect.ValueOf(int16(num.Int64()))) 111 112 case reflect.Int32: 113 num := new(big.Int).SetBytes(topics[0][:]) 114 field.Set(reflect.ValueOf(int32(num.Int64()))) 115 116 case reflect.Int64: 117 num := new(big.Int).SetBytes(topics[0][:]) 118 field.Set(reflect.ValueOf(num.Int64())) 119 120 case reflect.Uint8: 121 num := new(big.Int).SetBytes(topics[0][:]) 122 field.Set(reflect.ValueOf(uint8(num.Uint64()))) 123 124 case reflect.Uint16: 125 num := new(big.Int).SetBytes(topics[0][:]) 126 field.Set(reflect.ValueOf(uint16(num.Uint64()))) 127 128 case reflect.Uint32: 129 num := new(big.Int).SetBytes(topics[0][:]) 130 field.Set(reflect.ValueOf(uint32(num.Uint64()))) 131 132 case reflect.Uint64: 133 num := new(big.Int).SetBytes(topics[0][:]) 134 field.Set(reflect.ValueOf(num.Uint64())) 135 136 default: 137 138 switch field.Type() { 139 case reflectHash: 140 field.Set(reflect.ValueOf(topics[0])) 141 142 case reflectAddress: 143 var addr common.Address 144 copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) 145 field.Set(reflect.ValueOf(addr)) 146 147 case reflectBigInt: 148 num := new(big.Int).SetBytes(topics[0][:]) 149 if arg.Type.T == abi.IntTy { 150 if num.Cmp(abi.MaxInt256) > 0 { 151 num.Add(abi.MaxUint256, big.NewInt(0).Neg(num)) 152 num.Add(num, big.NewInt(1)) 153 num.Neg(num) 154 } 155 } 156 field.Set(reflect.ValueOf(num)) 157 158 default: 159 160 switch { 161 162 case arg.Type.T == abi.FixedBytesTy: 163 reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size])) 164 default: 165 return fmt.Errorf("unsupported indexed type: %v", arg.Type) 166 } 167 } 168 } 169 topics = topics[1:] 170 } 171 return nil 172 } 173 174 func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics []common.Hash) error { 175 176 if len(fields) != len(topics) { 177 return errors.New("topic/field count mismatch") 178 } 179 180 for _, arg := range fields { 181 if !arg.Indexed { 182 return errors.New("non-indexed field in topic reconstruction") 183 } 184 185 switch arg.Type.T { 186 case abi.BoolTy: 187 out[arg.Name] = topics[0][common.HashLength-1] == 1 188 case abi.IntTy, abi.UintTy: 189 out[arg.Name] = abi.ReadInteger(arg.Type.T, arg.Type.Kind, topics[0].Bytes()) 190 case abi.AddressTy: 191 var addr common.Address 192 copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) 193 out[arg.Name] = addr 194 case abi.HashTy: 195 out[arg.Name] = topics[0] 196 case abi.FixedBytesTy: 197 array, err := abi.ReadFixedBytes(arg.Type, topics[0].Bytes()) 198 if err != nil { 199 return err 200 } 201 out[arg.Name] = array 202 case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: 203 204 out[arg.Name] = topics[0] 205 case abi.FunctionTy: 206 if garbage := binary.BigEndian.Uint64(topics[0][0:8]); garbage != 0 { 207 return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[0].Bytes()) 208 } 209 var tmp [24]byte 210 copy(tmp[:], topics[0][8:32]) 211 out[arg.Name] = tmp 212 default: 213 return fmt.Errorf("unsupported indexed type: %v", arg.Type) 214 } 215 216 topics = topics[1:] 217 } 218 219 return nil 220 }