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