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