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 }