github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/accounts/abi/abi_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:26</date> 10 //</624342582310211584> 11 12 13 package abi 14 15 import ( 16 "bytes" 17 "encoding/hex" 18 "fmt" 19 "log" 20 "math/big" 21 "strings" 22 "testing" 23 24 "reflect" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/crypto" 28 ) 29 30 const jsondata = ` 31 [ 32 { "type" : "function", "name" : "balance", "constant" : true }, 33 { "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] } 34 ]` 35 36 const jsondata2 = ` 37 [ 38 { "type" : "function", "name" : "balance", "constant" : true }, 39 { "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }, 40 { "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] }, 41 { "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] }, 42 { "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] }, 43 { "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] }, 44 { "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] }, 45 { "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] }, 46 { "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] }, 47 { "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] }, 48 { "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] }, 49 { "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] }, 50 { "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] }, 51 { "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] } 52 ]` 53 54 func TestReader(t *testing.T) { 55 Uint256, _ := NewType("uint256") 56 exp := ABI{ 57 Methods: map[string]Method{ 58 "balance": { 59 "balance", true, nil, nil, 60 }, 61 "send": { 62 "send", false, []Argument{ 63 {"amount", Uint256, false}, 64 }, nil, 65 }, 66 }, 67 } 68 69 abi, err := JSON(strings.NewReader(jsondata)) 70 if err != nil { 71 t.Error(err) 72 } 73 74 //深相等由于某种原因而失败 75 for name, expM := range exp.Methods { 76 gotM, exist := abi.Methods[name] 77 if !exist { 78 t.Errorf("Missing expected method %v", name) 79 } 80 if !reflect.DeepEqual(gotM, expM) { 81 t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM) 82 } 83 } 84 85 for name, gotM := range abi.Methods { 86 expM, exist := exp.Methods[name] 87 if !exist { 88 t.Errorf("Found extra method %v", name) 89 } 90 if !reflect.DeepEqual(gotM, expM) { 91 t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM) 92 } 93 } 94 } 95 96 func TestTestNumbers(t *testing.T) { 97 abi, err := JSON(strings.NewReader(jsondata2)) 98 if err != nil { 99 t.Error(err) 100 t.FailNow() 101 } 102 103 if _, err := abi.Pack("balance"); err != nil { 104 t.Error(err) 105 } 106 107 if _, err := abi.Pack("balance", 1); err == nil { 108 t.Error("expected error for balance(1)") 109 } 110 111 if _, err := abi.Pack("doesntexist", nil); err == nil { 112 t.Errorf("doesntexist shouldn't exist") 113 } 114 115 if _, err := abi.Pack("doesntexist", 1); err == nil { 116 t.Errorf("doesntexist(1) shouldn't exist") 117 } 118 119 if _, err := abi.Pack("send", big.NewInt(1000)); err != nil { 120 t.Error(err) 121 } 122 123 i := new(int) 124 *i = 1000 125 if _, err := abi.Pack("send", i); err == nil { 126 t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int") 127 } 128 129 if _, err := abi.Pack("test", uint32(1000)); err != nil { 130 t.Error(err) 131 } 132 } 133 134 func TestTestString(t *testing.T) { 135 abi, err := JSON(strings.NewReader(jsondata2)) 136 if err != nil { 137 t.Error(err) 138 t.FailNow() 139 } 140 141 if _, err := abi.Pack("string", "hello world"); err != nil { 142 t.Error(err) 143 } 144 } 145 146 func TestTestBool(t *testing.T) { 147 abi, err := JSON(strings.NewReader(jsondata2)) 148 if err != nil { 149 t.Error(err) 150 t.FailNow() 151 } 152 153 if _, err := abi.Pack("bool", true); err != nil { 154 t.Error(err) 155 } 156 } 157 158 func TestTestSlice(t *testing.T) { 159 abi, err := JSON(strings.NewReader(jsondata2)) 160 if err != nil { 161 t.Error(err) 162 t.FailNow() 163 } 164 165 slice := make([]uint64, 2) 166 if _, err := abi.Pack("uint64[2]", slice); err != nil { 167 t.Error(err) 168 } 169 170 if _, err := abi.Pack("uint64[]", slice); err != nil { 171 t.Error(err) 172 } 173 } 174 175 func TestMethodSignature(t *testing.T) { 176 String, _ := NewType("string") 177 m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil} 178 exp := "foo(string,string)" 179 if m.Sig() != exp { 180 t.Error("signature mismatch", exp, "!=", m.Sig()) 181 } 182 183 idexp := crypto.Keccak256([]byte(exp))[:4] 184 if !bytes.Equal(m.Id(), idexp) { 185 t.Errorf("expected ids to match %x != %x", m.Id(), idexp) 186 } 187 188 uintt, _ := NewType("uint256") 189 m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil} 190 exp = "foo(uint256)" 191 if m.Sig() != exp { 192 t.Error("signature mismatch", exp, "!=", m.Sig()) 193 } 194 } 195 196 func TestMultiPack(t *testing.T) { 197 abi, err := JSON(strings.NewReader(jsondata2)) 198 if err != nil { 199 t.Error(err) 200 t.FailNow() 201 } 202 203 sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4] 204 sig = append(sig, make([]byte, 64)...) 205 sig[35] = 10 206 sig[67] = 11 207 208 packed, err := abi.Pack("bar", uint32(10), uint16(11)) 209 if err != nil { 210 t.Error(err) 211 t.FailNow() 212 } 213 214 if !bytes.Equal(packed, sig) { 215 t.Errorf("expected %x got %x", sig, packed) 216 } 217 } 218 219 func ExampleJSON() { 220 const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]` 221 222 abi, err := JSON(strings.NewReader(definition)) 223 if err != nil { 224 log.Fatalln(err) 225 } 226 out, err := abi.Pack("isBar", common.HexToAddress("01")) 227 if err != nil { 228 log.Fatalln(err) 229 } 230 231 fmt.Printf("%x\n", out) 232 //输出: 233 //1FBC40920000000000000000000000000000000000000000000000000000000000000000001 234 } 235 236 func TestInputVariableInputLength(t *testing.T) { 237 const definition = `[ 238 { "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] }, 239 { "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] }, 240 { "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] } 241 ]` 242 243 abi, err := JSON(strings.NewReader(definition)) 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 //测试一个字符串 249 strin := "hello world" 250 strpack, err := abi.Pack("strOne", strin) 251 if err != nil { 252 t.Error(err) 253 } 254 255 offset := make([]byte, 32) 256 offset[31] = 32 257 length := make([]byte, 32) 258 length[31] = byte(len(strin)) 259 value := common.RightPadBytes([]byte(strin), 32) 260 exp := append(offset, append(length, value...)...) 261 262 //忽略输出的前4个字节。这是函数标识符 263 strpack = strpack[4:] 264 if !bytes.Equal(strpack, exp) { 265 t.Errorf("expected %x, got %x\n", exp, strpack) 266 } 267 268 //测试一个字节 269 btspack, err := abi.Pack("bytesOne", []byte(strin)) 270 if err != nil { 271 t.Error(err) 272 } 273 //忽略输出的前4个字节。这是函数标识符 274 btspack = btspack[4:] 275 if !bytes.Equal(btspack, exp) { 276 t.Errorf("expected %x, got %x\n", exp, btspack) 277 } 278 279 //测试两个字符串 280 str1 := "hello" 281 str2 := "world" 282 str2pack, err := abi.Pack("strTwo", str1, str2) 283 if err != nil { 284 t.Error(err) 285 } 286 287 offset1 := make([]byte, 32) 288 offset1[31] = 64 289 length1 := make([]byte, 32) 290 length1[31] = byte(len(str1)) 291 value1 := common.RightPadBytes([]byte(str1), 32) 292 293 offset2 := make([]byte, 32) 294 offset2[31] = 128 295 length2 := make([]byte, 32) 296 length2[31] = byte(len(str2)) 297 value2 := common.RightPadBytes([]byte(str2), 32) 298 299 exp2 := append(offset1, offset2...) 300 exp2 = append(exp2, append(length1, value1...)...) 301 exp2 = append(exp2, append(length2, value2...)...) 302 303 //忽略输出的前4个字节。这是函数标识符 304 str2pack = str2pack[4:] 305 if !bytes.Equal(str2pack, exp2) { 306 t.Errorf("expected %x, got %x\n", exp, str2pack) 307 } 308 309 //测试两个字符串,第一个>32,第二个<32 310 str1 = strings.Repeat("a", 33) 311 str2pack, err = abi.Pack("strTwo", str1, str2) 312 if err != nil { 313 t.Error(err) 314 } 315 316 offset1 = make([]byte, 32) 317 offset1[31] = 64 318 length1 = make([]byte, 32) 319 length1[31] = byte(len(str1)) 320 value1 = common.RightPadBytes([]byte(str1), 64) 321 offset2[31] = 160 322 323 exp2 = append(offset1, offset2...) 324 exp2 = append(exp2, append(length1, value1...)...) 325 exp2 = append(exp2, append(length2, value2...)...) 326 327 //忽略输出的前4个字节。这是函数标识符 328 str2pack = str2pack[4:] 329 if !bytes.Equal(str2pack, exp2) { 330 t.Errorf("expected %x, got %x\n", exp, str2pack) 331 } 332 333 //测试两个字符串,第一个>32,第二个>32 334 str1 = strings.Repeat("a", 33) 335 str2 = strings.Repeat("a", 33) 336 str2pack, err = abi.Pack("strTwo", str1, str2) 337 if err != nil { 338 t.Error(err) 339 } 340 341 offset1 = make([]byte, 32) 342 offset1[31] = 64 343 length1 = make([]byte, 32) 344 length1[31] = byte(len(str1)) 345 value1 = common.RightPadBytes([]byte(str1), 64) 346 347 offset2 = make([]byte, 32) 348 offset2[31] = 160 349 length2 = make([]byte, 32) 350 length2[31] = byte(len(str2)) 351 value2 = common.RightPadBytes([]byte(str2), 64) 352 353 exp2 = append(offset1, offset2...) 354 exp2 = append(exp2, append(length1, value1...)...) 355 exp2 = append(exp2, append(length2, value2...)...) 356 357 //忽略输出的前4个字节。这是函数标识符 358 str2pack = str2pack[4:] 359 if !bytes.Equal(str2pack, exp2) { 360 t.Errorf("expected %x, got %x\n", exp, str2pack) 361 } 362 } 363 364 func TestInputFixedArrayAndVariableInputLength(t *testing.T) { 365 const definition = `[ 366 { "type" : "function", "name" : "fixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }, 367 { "type" : "function", "name" : "fixedArrBytes", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }, 368 { "type" : "function", "name" : "mixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type": "uint256[2]" }, { "name" : "dynArr", "type": "uint256[]" } ] }, 369 { "type" : "function", "name" : "doubleFixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type": "uint256[2]" }, { "name" : "fixedArr2", "type": "uint256[3]" } ] }, 370 { "type" : "function", "name" : "multipleMixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type": "uint256[2]" }, { "name" : "dynArr", "type" : "uint256[]" }, { "name" : "fixedArr2", "type" : "uint256[3]" } ] } 371 ]` 372 373 abi, err := JSON(strings.NewReader(definition)) 374 if err != nil { 375 t.Error(err) 376 } 377 378 //测试字符串,固定数组uint256[2] 379 strin := "hello world" 380 arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)} 381 fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin) 382 if err != nil { 383 t.Error(err) 384 } 385 386 //生成预期输出 387 offset := make([]byte, 32) 388 offset[31] = 96 389 length := make([]byte, 32) 390 length[31] = byte(len(strin)) 391 strvalue := common.RightPadBytes([]byte(strin), 32) 392 arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32) 393 arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32) 394 exp := append(offset, arrinvalue1...) 395 exp = append(exp, arrinvalue2...) 396 exp = append(exp, append(length, strvalue...)...) 397 398 //忽略输出的前4个字节。这是函数标识符 399 fixedArrStrPack = fixedArrStrPack[4:] 400 if !bytes.Equal(fixedArrStrPack, exp) { 401 t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack) 402 } 403 404 //测试字节数组,固定数组uint256[2] 405 bytesin := []byte(strin) 406 arrin = [2]*big.Int{big.NewInt(1), big.NewInt(2)} 407 fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin) 408 if err != nil { 409 t.Error(err) 410 } 411 412 //生成预期输出 413 offset = make([]byte, 32) 414 offset[31] = 96 415 length = make([]byte, 32) 416 length[31] = byte(len(strin)) 417 strvalue = common.RightPadBytes([]byte(strin), 32) 418 arrinvalue1 = common.LeftPadBytes(arrin[0].Bytes(), 32) 419 arrinvalue2 = common.LeftPadBytes(arrin[1].Bytes(), 32) 420 exp = append(offset, arrinvalue1...) 421 exp = append(exp, arrinvalue2...) 422 exp = append(exp, append(length, strvalue...)...) 423 424 //忽略输出的前4个字节。这是函数标识符 425 fixedArrBytesPack = fixedArrBytesPack[4:] 426 if !bytes.Equal(fixedArrBytesPack, exp) { 427 t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack) 428 } 429 430 //测试字符串,固定数组uint256[2],动态数组uint256[] 431 strin = "hello world" 432 fixedarrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)} 433 dynarrin := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} 434 mixedArrStrPack, err := abi.Pack("mixedArrStr", strin, fixedarrin, dynarrin) 435 if err != nil { 436 t.Error(err) 437 } 438 439 //生成预期输出 440 stroffset := make([]byte, 32) 441 stroffset[31] = 128 442 strlength := make([]byte, 32) 443 strlength[31] = byte(len(strin)) 444 strvalue = common.RightPadBytes([]byte(strin), 32) 445 fixedarrinvalue1 := common.LeftPadBytes(fixedarrin[0].Bytes(), 32) 446 fixedarrinvalue2 := common.LeftPadBytes(fixedarrin[1].Bytes(), 32) 447 dynarroffset := make([]byte, 32) 448 dynarroffset[31] = byte(160 + ((len(strin)/32)+1)*32) 449 dynarrlength := make([]byte, 32) 450 dynarrlength[31] = byte(len(dynarrin)) 451 dynarrinvalue1 := common.LeftPadBytes(dynarrin[0].Bytes(), 32) 452 dynarrinvalue2 := common.LeftPadBytes(dynarrin[1].Bytes(), 32) 453 dynarrinvalue3 := common.LeftPadBytes(dynarrin[2].Bytes(), 32) 454 exp = append(stroffset, fixedarrinvalue1...) 455 exp = append(exp, fixedarrinvalue2...) 456 exp = append(exp, dynarroffset...) 457 exp = append(exp, append(strlength, strvalue...)...) 458 dynarrarg := append(dynarrlength, dynarrinvalue1...) 459 dynarrarg = append(dynarrarg, dynarrinvalue2...) 460 dynarrarg = append(dynarrarg, dynarrinvalue3...) 461 exp = append(exp, dynarrarg...) 462 463 //忽略输出的前4个字节。这是函数标识符 464 mixedArrStrPack = mixedArrStrPack[4:] 465 if !bytes.Equal(mixedArrStrPack, exp) { 466 t.Errorf("expected %x, got %x\n", exp, mixedArrStrPack) 467 } 468 469 //测试字符串,固定数组uint256[2],固定数组uint256[3] 470 strin = "hello world" 471 fixedarrin1 := [2]*big.Int{big.NewInt(1), big.NewInt(2)} 472 fixedarrin2 := [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} 473 doubleFixedArrStrPack, err := abi.Pack("doubleFixedArrStr", strin, fixedarrin1, fixedarrin2) 474 if err != nil { 475 t.Error(err) 476 } 477 478 //生成预期输出 479 stroffset = make([]byte, 32) 480 stroffset[31] = 192 481 strlength = make([]byte, 32) 482 strlength[31] = byte(len(strin)) 483 strvalue = common.RightPadBytes([]byte(strin), 32) 484 fixedarrin1value1 := common.LeftPadBytes(fixedarrin1[0].Bytes(), 32) 485 fixedarrin1value2 := common.LeftPadBytes(fixedarrin1[1].Bytes(), 32) 486 fixedarrin2value1 := common.LeftPadBytes(fixedarrin2[0].Bytes(), 32) 487 fixedarrin2value2 := common.LeftPadBytes(fixedarrin2[1].Bytes(), 32) 488 fixedarrin2value3 := common.LeftPadBytes(fixedarrin2[2].Bytes(), 32) 489 exp = append(stroffset, fixedarrin1value1...) 490 exp = append(exp, fixedarrin1value2...) 491 exp = append(exp, fixedarrin2value1...) 492 exp = append(exp, fixedarrin2value2...) 493 exp = append(exp, fixedarrin2value3...) 494 exp = append(exp, append(strlength, strvalue...)...) 495 496 //忽略输出的前4个字节。这是函数标识符 497 doubleFixedArrStrPack = doubleFixedArrStrPack[4:] 498 if !bytes.Equal(doubleFixedArrStrPack, exp) { 499 t.Errorf("expected %x, got %x\n", exp, doubleFixedArrStrPack) 500 } 501 502 //测试字符串,固定数组uint256[2],动态数组uint256[],固定数组uint256[3] 503 strin = "hello world" 504 fixedarrin1 = [2]*big.Int{big.NewInt(1), big.NewInt(2)} 505 dynarrin = []*big.Int{big.NewInt(1), big.NewInt(2)} 506 fixedarrin2 = [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} 507 multipleMixedArrStrPack, err := abi.Pack("multipleMixedArrStr", strin, fixedarrin1, dynarrin, fixedarrin2) 508 if err != nil { 509 t.Error(err) 510 } 511 512 //生成预期输出 513 stroffset = make([]byte, 32) 514 stroffset[31] = 224 515 strlength = make([]byte, 32) 516 strlength[31] = byte(len(strin)) 517 strvalue = common.RightPadBytes([]byte(strin), 32) 518 fixedarrin1value1 = common.LeftPadBytes(fixedarrin1[0].Bytes(), 32) 519 fixedarrin1value2 = common.LeftPadBytes(fixedarrin1[1].Bytes(), 32) 520 dynarroffset = U256(big.NewInt(int64(256 + ((len(strin)/32)+1)*32))) 521 dynarrlength = make([]byte, 32) 522 dynarrlength[31] = byte(len(dynarrin)) 523 dynarrinvalue1 = common.LeftPadBytes(dynarrin[0].Bytes(), 32) 524 dynarrinvalue2 = common.LeftPadBytes(dynarrin[1].Bytes(), 32) 525 fixedarrin2value1 = common.LeftPadBytes(fixedarrin2[0].Bytes(), 32) 526 fixedarrin2value2 = common.LeftPadBytes(fixedarrin2[1].Bytes(), 32) 527 fixedarrin2value3 = common.LeftPadBytes(fixedarrin2[2].Bytes(), 32) 528 exp = append(stroffset, fixedarrin1value1...) 529 exp = append(exp, fixedarrin1value2...) 530 exp = append(exp, dynarroffset...) 531 exp = append(exp, fixedarrin2value1...) 532 exp = append(exp, fixedarrin2value2...) 533 exp = append(exp, fixedarrin2value3...) 534 exp = append(exp, append(strlength, strvalue...)...) 535 dynarrarg = append(dynarrlength, dynarrinvalue1...) 536 dynarrarg = append(dynarrarg, dynarrinvalue2...) 537 exp = append(exp, dynarrarg...) 538 539 //忽略输出的前4个字节。这是函数标识符 540 multipleMixedArrStrPack = multipleMixedArrStrPack[4:] 541 if !bytes.Equal(multipleMixedArrStrPack, exp) { 542 t.Errorf("expected %x, got %x\n", exp, multipleMixedArrStrPack) 543 } 544 } 545 546 func TestDefaultFunctionParsing(t *testing.T) { 547 const definition = `[{ "name" : "balance" }]` 548 549 abi, err := JSON(strings.NewReader(definition)) 550 if err != nil { 551 t.Fatal(err) 552 } 553 554 if _, ok := abi.Methods["balance"]; !ok { 555 t.Error("expected 'balance' to be present") 556 } 557 } 558 559 func TestBareEvents(t *testing.T) { 560 const definition = `[ 561 { "type" : "event", "name" : "balance" }, 562 { "type" : "event", "name" : "anon", "anonymous" : true}, 563 { "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] } 564 ]` 565 566 arg0, _ := NewType("uint256") 567 arg1, _ := NewType("address") 568 569 expectedEvents := map[string]struct { 570 Anonymous bool 571 Args []Argument 572 }{ 573 "balance": {false, nil}, 574 "anon": {true, nil}, 575 "args": {false, []Argument{ 576 {Name: "arg0", Type: arg0, Indexed: false}, 577 {Name: "arg1", Type: arg1, Indexed: true}, 578 }}, 579 } 580 581 abi, err := JSON(strings.NewReader(definition)) 582 if err != nil { 583 t.Fatal(err) 584 } 585 586 if len(abi.Events) != len(expectedEvents) { 587 t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events)) 588 } 589 590 for name, exp := range expectedEvents { 591 got, ok := abi.Events[name] 592 if !ok { 593 t.Errorf("could not found event %s", name) 594 continue 595 } 596 if got.Anonymous != exp.Anonymous { 597 t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous) 598 } 599 if len(got.Inputs) != len(exp.Args) { 600 t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs)) 601 continue 602 } 603 for i, arg := range exp.Args { 604 if arg.Name != got.Inputs[i].Name { 605 t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name) 606 } 607 if arg.Indexed != got.Inputs[i].Indexed { 608 t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed) 609 } 610 if arg.Type.T != got.Inputs[i].Type.T { 611 t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T) 612 } 613 } 614 } 615 } 616 617 //TestUnpackEvent基于此合同: 618 //合同t{ 619 //接收到的事件(地址发送方、uint金额、字节备忘录); 620 //事件接收数据(地址发送者); 621 //功能接收(字节备忘录)外部应付款 622 //接收(msg.sender,msg.value,memo); 623 //接收数据(消息发送方); 624 //} 625 //} 626 //当使用发送方0x00调用Receive(“X”)时…以及值1,它生成此Tx收据: 627 //收据状态=1 cgas=23949 bloom=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[日志:B6818C8064F645CD82D99B59A1267D61117EF[75FD880D39C1DAF53B6547AB6CB59451FC6452D27CAA90E5B6649DD8293B9EED]000000000000000376C47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f43425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c4323DE162CF00 0 } 628 func TestUnpackEvent(t *testing.T) { 629 const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]` 630 abi, err := JSON(strings.NewReader(abiJSON)) 631 if err != nil { 632 t.Fatal(err) 633 } 634 635 const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158` 636 data, err := hex.DecodeString(hexdata) 637 if err != nil { 638 t.Fatal(err) 639 } 640 if len(data)%32 == 0 { 641 t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) 642 } 643 644 type ReceivedEvent struct { 645 Address common.Address 646 Amount *big.Int 647 Memo []byte 648 } 649 var ev ReceivedEvent 650 651 err = abi.Unpack(&ev, "received", data) 652 if err != nil { 653 t.Error(err) 654 } else { 655 t.Logf("len(data): %d; received event: %+v", len(data), ev) 656 } 657 658 type ReceivedAddrEvent struct { 659 Address common.Address 660 } 661 var receivedAddrEv ReceivedAddrEvent 662 err = abi.Unpack(&receivedAddrEv, "receivedAddr", data) 663 if err != nil { 664 t.Error(err) 665 } else { 666 t.Logf("len(data): %d; received event: %+v", len(data), receivedAddrEv) 667 } 668 } 669 670 func TestABI_MethodById(t *testing.T) { 671 const abiJSON = `[ 672 {"type":"function","name":"receive","constant":false,"inputs":[{"name":"memo","type":"bytes"}],"outputs":[],"payable":true,"stateMutability":"payable"}, 673 {"type":"event","name":"received","anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}]}, 674 {"type":"function","name":"fixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"}]}, 675 {"type":"function","name":"fixedArrBytes","constant":true,"inputs":[{"name":"str","type":"bytes"},{"name":"fixedArr","type":"uint256[2]"}]}, 676 {"type":"function","name":"mixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"},{"name":"dynArr","type":"uint256[]"}]}, 677 {"type":"function","name":"doubleFixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr1","type":"uint256[2]"},{"name":"fixedArr2","type":"uint256[3]"}]}, 678 {"type":"function","name":"multipleMixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr1","type":"uint256[2]"},{"name":"dynArr","type":"uint256[]"},{"name":"fixedArr2","type":"uint256[3]"}]}, 679 {"type":"function","name":"balance","constant":true}, 680 {"type":"function","name":"send","constant":false,"inputs":[{"name":"amount","type":"uint256"}]}, 681 {"type":"function","name":"test","constant":false,"inputs":[{"name":"number","type":"uint32"}]}, 682 {"type":"function","name":"string","constant":false,"inputs":[{"name":"inputs","type":"string"}]}, 683 {"type":"function","name":"bool","constant":false,"inputs":[{"name":"inputs","type":"bool"}]}, 684 {"type":"function","name":"address","constant":false,"inputs":[{"name":"inputs","type":"address"}]}, 685 {"type":"function","name":"uint64[2]","constant":false,"inputs":[{"name":"inputs","type":"uint64[2]"}]}, 686 {"type":"function","name":"uint64[]","constant":false,"inputs":[{"name":"inputs","type":"uint64[]"}]}, 687 {"type":"function","name":"foo","constant":false,"inputs":[{"name":"inputs","type":"uint32"}]}, 688 {"type":"function","name":"bar","constant":false,"inputs":[{"name":"inputs","type":"uint32"},{"name":"string","type":"uint16"}]}, 689 {"type":"function","name":"_slice","constant":false,"inputs":[{"name":"inputs","type":"uint32[2]"}]}, 690 {"type":"function","name":"__slice256","constant":false,"inputs":[{"name":"inputs","type":"uint256[2]"}]}, 691 {"type":"function","name":"sliceAddress","constant":false,"inputs":[{"name":"inputs","type":"address[]"}]}, 692 {"type":"function","name":"sliceMultiAddress","constant":false,"inputs":[{"name":"a","type":"address[]"},{"name":"b","type":"address[]"}]} 693 ] 694 ` 695 abi, err := JSON(strings.NewReader(abiJSON)) 696 if err != nil { 697 t.Fatal(err) 698 } 699 for name, m := range abi.Methods { 700 a := fmt.Sprintf("%v", m) 701 m2, err := abi.MethodById(m.Id()) 702 if err != nil { 703 t.Fatalf("Failed to look up ABI method: %v", err) 704 } 705 b := fmt.Sprintf("%v", m2) 706 if a != b { 707 t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.Id())) 708 } 709 } 710 711 } 712