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  }