github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/accounts/abi/event_test.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package abi
    13  
    14  import (
    15  	"bytes"
    16  	"encoding/hex"
    17  	"encoding/json"
    18  	"math/big"
    19  	"reflect"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/Sberex/go-sberex/common"
    24  	"github.com/Sberex/go-sberex/crypto"
    25  	"github.com/stretchr/testify/assert"
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  var jsonEventTransfer = []byte(`{
    30    "anonymous": false,
    31    "inputs": [
    32      {
    33        "indexed": true, "name": "from", "type": "address"
    34      }, {
    35        "indexed": true, "name": "to", "type": "address"
    36      }, {
    37        "indexed": false, "name": "value", "type": "uint256"
    38    }],
    39    "name": "Transfer",
    40    "type": "event"
    41  }`)
    42  
    43  var jsonEventPledge = []byte(`{
    44    "anonymous": false,
    45    "inputs": [{
    46        "indexed": false, "name": "who", "type": "address"
    47      }, {
    48        "indexed": false, "name": "wad", "type": "uint128"
    49      }, {
    50        "indexed": false, "name": "currency", "type": "bytes3"
    51    }],
    52    "name": "Pledge",
    53    "type": "event"
    54  }`)
    55  
    56  // 1000000
    57  var transferData1 = "00000000000000000000000000000000000000000000000000000000000f4240"
    58  
    59  // "0x00Ce0d46d924CC8437c806721496599FC3FFA268", 2218516807680, "usd"
    60  var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa2680000000000000000000000000000000000000000000000000000020489e800007573640000000000000000000000000000000000000000000000000000000000"
    61  
    62  func TestEventId(t *testing.T) {
    63  	var table = []struct {
    64  		definition   string
    65  		expectations map[string]common.Hash
    66  	}{
    67  		{
    68  			definition: `[
    69  			{ "type" : "event", "name" : "balance", "inputs": [{ "name" : "in", "type": "uint256" }] },
    70  			{ "type" : "event", "name" : "check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] }
    71  			]`,
    72  			expectations: map[string]common.Hash{
    73  				"balance": crypto.Keccak256Hash([]byte("balance(uint256)")),
    74  				"check":   crypto.Keccak256Hash([]byte("check(address,uint256)")),
    75  			},
    76  		},
    77  	}
    78  
    79  	for _, test := range table {
    80  		abi, err := JSON(strings.NewReader(test.definition))
    81  		if err != nil {
    82  			t.Fatal(err)
    83  		}
    84  
    85  		for name, event := range abi.Events {
    86  			if event.Id() != test.expectations[name] {
    87  				t.Errorf("expected id to be %x, got %x", test.expectations[name], event.Id())
    88  			}
    89  		}
    90  	}
    91  }
    92  
    93  // TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
    94  func TestEventMultiValueWithArrayUnpack(t *testing.T) {
    95  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
    96  	type testStruct struct {
    97  		Value1 [2]uint8
    98  		Value2 uint8
    99  	}
   100  	abi, err := JSON(strings.NewReader(definition))
   101  	require.NoError(t, err)
   102  	var b bytes.Buffer
   103  	var i uint8 = 1
   104  	for ; i <= 3; i++ {
   105  		b.Write(packNum(reflect.ValueOf(i)))
   106  	}
   107  	var rst testStruct
   108  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   109  	require.Equal(t, [2]uint8{1, 2}, rst.Value1)
   110  	require.Equal(t, uint8(3), rst.Value2)
   111  }
   112  
   113  func TestEventTupleUnpack(t *testing.T) {
   114  
   115  	type EventTransfer struct {
   116  		Value *big.Int
   117  	}
   118  
   119  	type EventPledge struct {
   120  		Who      common.Address
   121  		Wad      *big.Int
   122  		Currency [3]byte
   123  	}
   124  
   125  	type BadEventPledge struct {
   126  		Who      string
   127  		Wad      int
   128  		Currency [3]byte
   129  	}
   130  
   131  	bigint := new(big.Int)
   132  	bigintExpected := big.NewInt(1000000)
   133  	bigintExpected2 := big.NewInt(2218516807680)
   134  	addr := common.HexToAddress("0x00Ce0d46d924CC8437c806721496599FC3FFA268")
   135  	var testCases = []struct {
   136  		data     string
   137  		dest     interface{}
   138  		expected interface{}
   139  		jsonLog  []byte
   140  		error    string
   141  		name     string
   142  	}{{
   143  		transferData1,
   144  		&EventTransfer{},
   145  		&EventTransfer{Value: bigintExpected},
   146  		jsonEventTransfer,
   147  		"",
   148  		"Can unpack ERC20 Transfer event into structure",
   149  	}, {
   150  		transferData1,
   151  		&[]interface{}{&bigint},
   152  		&[]interface{}{&bigintExpected},
   153  		jsonEventTransfer,
   154  		"",
   155  		"Can unpack ERC20 Transfer event into slice",
   156  	}, {
   157  		pledgeData1,
   158  		&EventPledge{},
   159  		&EventPledge{
   160  			addr,
   161  			bigintExpected2,
   162  			[3]byte{'u', 's', 'd'}},
   163  		jsonEventPledge,
   164  		"",
   165  		"Can unpack Pledge event into structure",
   166  	}, {
   167  		pledgeData1,
   168  		&[]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   169  		&[]interface{}{
   170  			&addr,
   171  			&bigintExpected2,
   172  			&[3]byte{'u', 's', 'd'}},
   173  		jsonEventPledge,
   174  		"",
   175  		"Can unpack Pledge event into slice",
   176  	}, {
   177  		pledgeData1,
   178  		&[3]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   179  		&[3]interface{}{
   180  			&addr,
   181  			&bigintExpected2,
   182  			&[3]byte{'u', 's', 'd'}},
   183  		jsonEventPledge,
   184  		"",
   185  		"Can unpack Pledge event into an array",
   186  	}, {
   187  		pledgeData1,
   188  		&[]interface{}{new(int), 0, 0},
   189  		&[]interface{}{},
   190  		jsonEventPledge,
   191  		"abi: cannot unmarshal common.Address in to int",
   192  		"Can not unpack Pledge event into slice with wrong types",
   193  	}, {
   194  		pledgeData1,
   195  		&BadEventPledge{},
   196  		&BadEventPledge{},
   197  		jsonEventPledge,
   198  		"abi: cannot unmarshal common.Address in to string",
   199  		"Can not unpack Pledge event into struct with wrong filed types",
   200  	}, {
   201  		pledgeData1,
   202  		&[]interface{}{common.Address{}, new(big.Int)},
   203  		&[]interface{}{},
   204  		jsonEventPledge,
   205  		"abi: insufficient number of elements in the list/array for unpack, want 3, got 2",
   206  		"Can not unpack Pledge event into too short slice",
   207  	}, {
   208  		pledgeData1,
   209  		new(map[string]interface{}),
   210  		&[]interface{}{},
   211  		jsonEventPledge,
   212  		"abi: cannot unmarshal tuple into map[string]interface {}",
   213  		"Can not unpack Pledge event into map",
   214  	}}
   215  
   216  	for _, tc := range testCases {
   217  		assert := assert.New(t)
   218  		tc := tc
   219  		t.Run(tc.name, func(t *testing.T) {
   220  			err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
   221  			if tc.error == "" {
   222  				assert.Nil(err, "Should be able to unpack event data.")
   223  				assert.Equal(tc.expected, tc.dest, tc.name)
   224  			} else {
   225  				assert.EqualError(err, tc.error)
   226  			}
   227  		})
   228  	}
   229  }
   230  
   231  func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, assert *assert.Assertions) error {
   232  	data, err := hex.DecodeString(hexData)
   233  	assert.NoError(err, "Hex data should be a correct hex-string")
   234  	var e Event
   235  	assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI")
   236  	a := ABI{Events: map[string]Event{"e": e}}
   237  	return a.Unpack(dest, "e", data)
   238  }
   239  
   240  /*
   241  Taken from
   242  https://github.com/Sberex/go-sberex/pull/15568
   243  */
   244  
   245  type testResult struct {
   246  	Values [2]*big.Int
   247  	Value1 *big.Int
   248  	Value2 *big.Int
   249  }
   250  
   251  type testCase struct {
   252  	definition string
   253  	want       testResult
   254  }
   255  
   256  func (tc testCase) encoded(intType, arrayType Type) []byte {
   257  	var b bytes.Buffer
   258  	if tc.want.Value1 != nil {
   259  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value1))
   260  		b.Write(val)
   261  	}
   262  
   263  	if !reflect.DeepEqual(tc.want.Values, [2]*big.Int{nil, nil}) {
   264  		val, _ := arrayType.pack(reflect.ValueOf(tc.want.Values))
   265  		b.Write(val)
   266  	}
   267  	if tc.want.Value2 != nil {
   268  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value2))
   269  		b.Write(val)
   270  	}
   271  	return b.Bytes()
   272  }
   273  
   274  // TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
   275  func TestEventUnpackIndexed(t *testing.T) {
   276  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
   277  	type testStruct struct {
   278  		Value1 uint8
   279  		Value2 uint8
   280  	}
   281  	abi, err := JSON(strings.NewReader(definition))
   282  	require.NoError(t, err)
   283  	var b bytes.Buffer
   284  	b.Write(packNum(reflect.ValueOf(uint8(8))))
   285  	var rst testStruct
   286  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   287  	require.Equal(t, uint8(0), rst.Value1)
   288  	require.Equal(t, uint8(8), rst.Value2)
   289  }
   290  
   291  // TestEventIndexedWithArrayUnpack verifies that decoder will not overlow when static array is indexed input.
   292  func TestEventIndexedWithArrayUnpack(t *testing.T) {
   293  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
   294  	type testStruct struct {
   295  		Value1 [2]uint8
   296  		Value2 string
   297  	}
   298  	abi, err := JSON(strings.NewReader(definition))
   299  	require.NoError(t, err)
   300  	var b bytes.Buffer
   301  	stringOut := "abc"
   302  	// number of fields that will be encoded * 32
   303  	b.Write(packNum(reflect.ValueOf(32)))
   304  	b.Write(packNum(reflect.ValueOf(len(stringOut))))
   305  	b.Write(common.RightPadBytes([]byte(stringOut), 32))
   306  
   307  	var rst testStruct
   308  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   309  	require.Equal(t, [2]uint8{0, 0}, rst.Value1)
   310  	require.Equal(t, stringOut, rst.Value2)
   311  }