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