github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/accounts/abi/event_test.go (about)

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