github.com/lmittmann/w3@v0.20.0/internal/abi/parser_test.go (about) 1 package abi 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "testing" 8 9 "github.com/ethereum/go-ethereum/accounts/abi" 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/google/go-cmp/cmp" 12 "github.com/google/go-cmp/cmp/cmpopts" 13 "github.com/lmittmann/w3/internal" 14 ) 15 16 var ( 17 typeAddress = abi.Type{T: abi.AddressTy, Size: 20} 18 typeBool = abi.Type{T: abi.BoolTy} 19 typeUint24 = abi.Type{T: abi.UintTy, Size: 24} 20 typeUint160 = abi.Type{T: abi.UintTy, Size: 160} 21 typeUint256 = abi.Type{T: abi.UintTy, Size: 256} 22 ) 23 24 func TestParseArgs(t *testing.T) { 25 tests := []struct { 26 Input string 27 Tuples []any 28 WantArgs Arguments 29 WantErr error 30 }{ 31 { 32 Input: "", 33 WantArgs: Arguments{}, 34 }, 35 { 36 Input: "xxx", 37 WantErr: errors.New(`syntax error: unexpected "xxx", expecting type`), 38 }, 39 { 40 Input: "uint256", 41 WantArgs: Arguments{{Type: typeUint256}}, 42 }, 43 { 44 Input: "uint", 45 WantArgs: Arguments{{Type: typeUint256}}, 46 }, 47 { 48 Input: "uint256 balance", 49 WantArgs: Arguments{{Type: typeUint256, Name: "balance"}}, 50 }, 51 { 52 Input: "uint256 indexed balance", 53 WantArgs: Arguments{{Type: typeUint256, Indexed: true, Name: "balance"}}, 54 }, 55 { 56 Input: "uint256 indexed", 57 WantArgs: Arguments{{Type: typeUint256, Indexed: true}}, 58 }, 59 { 60 Input: "uint256[]", 61 WantArgs: Arguments{{Type: abi.Type{Elem: &typeUint256, T: abi.SliceTy}}}, 62 }, 63 { 64 Input: "uint256[3]", 65 WantArgs: Arguments{{Type: abi.Type{Elem: &typeUint256, T: abi.ArrayTy, Size: 3}}}, 66 }, 67 { 68 Input: "uint256[][]", 69 WantArgs: Arguments{{ 70 Type: abi.Type{ 71 Elem: &abi.Type{Elem: &typeUint256, T: abi.SliceTy}, 72 T: abi.SliceTy, 73 }, 74 }}, 75 }, 76 { 77 Input: "uint256[][3]", 78 WantArgs: Arguments{{ 79 Type: abi.Type{ 80 Elem: &abi.Type{Elem: &typeUint256, T: abi.SliceTy}, 81 T: abi.ArrayTy, 82 Size: 3, 83 }, 84 }}, 85 }, 86 { 87 Input: "uint256[3][]", 88 WantArgs: Arguments{{ 89 Type: abi.Type{ 90 Elem: &abi.Type{Elem: &typeUint256, T: abi.ArrayTy, Size: 3}, 91 T: abi.SliceTy, 92 }, 93 }}, 94 }, 95 { 96 Input: "uint256[],uint256[3],uint256[][3],uint256[3][]", 97 WantArgs: Arguments{ 98 {Type: abi.Type{T: abi.SliceTy, Elem: &typeUint256}}, 99 {Type: abi.Type{T: abi.ArrayTy, Size: 3, Elem: &typeUint256}}, 100 {Type: abi.Type{T: abi.ArrayTy, Size: 3, Elem: &abi.Type{T: abi.SliceTy, Elem: &typeUint256}}}, 101 {Type: abi.Type{T: abi.SliceTy, Elem: &abi.Type{T: abi.ArrayTy, Size: 3, Elem: &typeUint256}}}, 102 }, 103 }, 104 { 105 Input: "uint256[", 106 WantErr: errors.New(`syntax error: unexpected EOF, expecting "]"`), 107 }, 108 { 109 Input: "uint256[3", 110 WantErr: errors.New(`syntax error: unexpected EOF, expecting "]"`), 111 }, 112 { 113 Input: "(uint256 arg0)", 114 WantArgs: Arguments{{ 115 Type: abi.Type{ 116 T: abi.TupleTy, 117 TupleElems: []*abi.Type{&typeUint256}, 118 TupleRawNames: []string{"arg0"}, 119 }, 120 }}, 121 }, 122 { 123 Input: "(uint256 arg0)[]", 124 WantArgs: Arguments{{ 125 Type: abi.Type{ 126 Elem: &abi.Type{ 127 T: abi.TupleTy, 128 TupleElems: []*abi.Type{&typeUint256}, 129 TupleRawNames: []string{"arg0"}, 130 }, 131 T: abi.SliceTy, 132 }, 133 }}, 134 }, 135 { 136 Input: "(uint256 arg0)[3]", 137 WantArgs: Arguments{{ 138 Type: abi.Type{ 139 Elem: &abi.Type{ 140 T: abi.TupleTy, 141 TupleElems: []*abi.Type{&typeUint256}, 142 TupleRawNames: []string{"arg0"}, 143 }, 144 T: abi.ArrayTy, 145 Size: 3, 146 }, 147 }}, 148 }, 149 { 150 Input: "uint256,(uint256 v0,uint256 v1),((uint256 v00,uint256 v01) v0,uint256 v1)", 151 WantArgs: Arguments{ 152 {Type: typeUint256}, 153 {Type: abi.Type{T: abi.TupleTy, TupleElems: []*abi.Type{&typeUint256, &typeUint256}, TupleRawNames: []string{"v0", "v1"}}}, 154 {Type: abi.Type{T: abi.TupleTy, TupleElems: []*abi.Type{ 155 {T: abi.TupleTy, TupleElems: []*abi.Type{&typeUint256, &typeUint256}, TupleRawNames: []string{"v00", "v01"}}, 156 &typeUint256, 157 }, TupleRawNames: []string{"v0", "v1"}}}, 158 }, 159 }, 160 { 161 Input: "simpleStruct", 162 Tuples: []any{simpleStruct{}}, 163 WantArgs: Arguments{{ 164 Type: abi.Type{ 165 T: abi.TupleTy, 166 TupleRawName: "simpleStruct", 167 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 168 TupleRawNames: []string{"amount", "token"}, 169 }, 170 }}, 171 }, 172 { 173 Input: "simpleStructWithoutTags", 174 Tuples: []any{simpleStructWithoutTags{}}, 175 WantArgs: Arguments{{ 176 Type: abi.Type{ 177 T: abi.TupleTy, 178 TupleRawName: "simpleStructWithoutTags", 179 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 180 TupleRawNames: []string{"amount", "token"}, 181 }, 182 }}, 183 }, 184 { 185 Input: "simpleStruct[]", 186 Tuples: []any{simpleStruct{}}, 187 WantArgs: Arguments{{ 188 Type: abi.Type{ 189 T: abi.SliceTy, 190 Elem: &abi.Type{ 191 T: abi.TupleTy, 192 TupleRawName: "simpleStruct", 193 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 194 TupleRawNames: []string{"amount", "token"}, 195 }, 196 }, 197 }}, 198 }, 199 { 200 Input: "simpleStruct[3]", 201 Tuples: []any{simpleStruct{}}, 202 WantArgs: Arguments{{ 203 Type: abi.Type{ 204 T: abi.ArrayTy, 205 Size: 3, 206 Elem: &abi.Type{ 207 T: abi.TupleTy, 208 TupleRawName: "simpleStruct", 209 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 210 TupleRawNames: []string{"amount", "token"}, 211 }, 212 }, 213 }}, 214 }, 215 { 216 Input: "uint256,simpleStruct,address", 217 Tuples: []any{simpleStruct{}}, 218 WantArgs: Arguments{ 219 {Type: typeUint256}, 220 { 221 Type: abi.Type{ 222 T: abi.TupleTy, 223 TupleRawName: "simpleStruct", 224 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 225 TupleRawNames: []string{"amount", "token"}, 226 }, 227 }, 228 {Type: typeAddress}, 229 }, 230 }, 231 { 232 Input: "emptyStruct", 233 Tuples: []any{emptyStruct{}}, 234 WantArgs: Arguments{{ 235 Type: abi.Type{ 236 T: abi.TupleTy, 237 TupleRawName: "emptyStruct", 238 TupleElems: []*abi.Type{}, 239 TupleRawNames: []string{}, 240 }, 241 }}, 242 }, 243 { 244 Input: "unknownStruct", 245 Tuples: []any{simpleStruct{}}, 246 WantErr: errors.New(`syntax error: unexpected "unknownStruct", expecting type`), 247 }, 248 { 249 Input: "simpleStruct", 250 Tuples: []any{}, // no tuples provided 251 WantErr: errors.New(`syntax error: unexpected "simpleStruct", expecting type`), 252 }, 253 { 254 Input: "simpleStruct", 255 Tuples: []any{simpleStruct{}, simpleStruct{}}, 256 WantErr: errors.New(`syntax error: duplicate tuple definition: simpleStruct`), 257 }, 258 { 259 Input: "nestedStruct", 260 Tuples: []any{nestedStruct{}}, 261 WantArgs: Arguments{{ 262 Type: abi.Type{ 263 T: abi.TupleTy, 264 TupleRawName: "nestedStruct", 265 TupleElems: []*abi.Type{ 266 { 267 T: abi.TupleTy, 268 TupleRawName: "simpleStruct", 269 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 270 TupleRawNames: []string{"amount", "token"}, 271 }, 272 &typeBool, 273 }, 274 TupleRawNames: []string{"inner", "active"}, 275 }, 276 }}, 277 }, 278 { 279 Input: "nestedStruct[]", 280 Tuples: []any{nestedStruct{}}, 281 WantArgs: Arguments{{ 282 Type: abi.Type{ 283 T: abi.SliceTy, 284 Elem: &abi.Type{ 285 T: abi.TupleTy, 286 TupleRawName: "nestedStruct", 287 TupleElems: []*abi.Type{ 288 { 289 T: abi.TupleTy, 290 TupleRawName: "simpleStruct", 291 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 292 TupleRawNames: []string{"amount", "token"}, 293 }, 294 &typeBool, 295 }, 296 TupleRawNames: []string{"inner", "active"}, 297 }, 298 }, 299 }}, 300 }, 301 { 302 Input: "complexStruct", 303 Tuples: []any{complexStruct{}}, 304 WantArgs: Arguments{{ 305 Type: abi.Type{ 306 T: abi.TupleTy, 307 TupleRawName: "complexStruct", 308 TupleElems: []*abi.Type{ 309 &typeUint256, 310 &typeAddress, 311 {T: abi.BytesTy}, 312 { 313 T: abi.TupleTy, 314 TupleRawName: "nestedStruct", 315 TupleElems: []*abi.Type{ 316 { 317 T: abi.TupleTy, 318 TupleRawName: "simpleStruct", 319 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 320 TupleRawNames: []string{"amount", "token"}, 321 }, 322 &typeBool, 323 }, 324 TupleRawNames: []string{"inner", "active"}, 325 }, 326 }, 327 TupleRawNames: []string{"id", "owner", "data", "metadata"}, 328 }, 329 }}, 330 }, 331 { 332 Input: "complexStruct[2]", 333 Tuples: []any{complexStruct{}}, 334 WantArgs: Arguments{{ 335 Type: abi.Type{ 336 T: abi.ArrayTy, 337 Size: 2, 338 Elem: &abi.Type{ 339 T: abi.TupleTy, 340 TupleRawName: "complexStruct", 341 TupleElems: []*abi.Type{ 342 &typeUint256, 343 &typeAddress, 344 {T: abi.BytesTy}, 345 { 346 T: abi.TupleTy, 347 TupleRawName: "nestedStruct", 348 TupleElems: []*abi.Type{ 349 { 350 T: abi.TupleTy, 351 TupleRawName: "simpleStruct", 352 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 353 TupleRawNames: []string{"amount", "token"}, 354 }, 355 &typeBool, 356 }, 357 TupleRawNames: []string{"inner", "active"}, 358 }, 359 }, 360 TupleRawNames: []string{"id", "owner", "data", "metadata"}, 361 }, 362 }, 363 }}, 364 }, 365 { 366 Input: "arrayStruct", 367 Tuples: []any{arrayStruct{}}, 368 WantArgs: Arguments{{ 369 Type: abi.Type{ 370 T: abi.TupleTy, 371 TupleRawName: "arrayStruct", 372 TupleElems: []*abi.Type{ 373 {T: abi.SliceTy, Elem: &typeUint256}, 374 &typeUint256, 375 }, 376 TupleRawNames: []string{"values", "count"}, 377 }, 378 }}, 379 }, 380 { 381 Input: "arrayStruct[]", 382 Tuples: []any{arrayStruct{}}, 383 WantArgs: Arguments{{ 384 Type: abi.Type{ 385 T: abi.SliceTy, 386 Elem: &abi.Type{ 387 T: abi.TupleTy, 388 TupleRawName: "arrayStruct", 389 TupleElems: []*abi.Type{ 390 {T: abi.SliceTy, Elem: &typeUint256}, 391 &typeUint256, 392 }, 393 TupleRawNames: []string{"values", "count"}, 394 }, 395 }, 396 }}, 397 }, 398 { 399 Input: "uint256,nestedStruct,complexStruct,arrayStruct", 400 Tuples: []any{nestedStruct{}, complexStruct{}, arrayStruct{}}, 401 WantArgs: Arguments{ 402 {Type: typeUint256}, 403 { 404 Type: abi.Type{ 405 T: abi.TupleTy, 406 TupleRawName: "nestedStruct", 407 TupleElems: []*abi.Type{ 408 { 409 T: abi.TupleTy, 410 TupleRawName: "simpleStruct", 411 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 412 TupleRawNames: []string{"amount", "token"}, 413 }, 414 &typeBool, 415 }, 416 TupleRawNames: []string{"inner", "active"}, 417 }, 418 }, 419 { 420 Type: abi.Type{ 421 T: abi.TupleTy, 422 TupleRawName: "complexStruct", 423 TupleElems: []*abi.Type{ 424 &typeUint256, 425 &typeAddress, 426 {T: abi.BytesTy}, 427 { 428 T: abi.TupleTy, 429 TupleRawName: "nestedStruct", 430 TupleElems: []*abi.Type{ 431 { 432 T: abi.TupleTy, 433 TupleRawName: "simpleStruct", 434 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 435 TupleRawNames: []string{"amount", "token"}, 436 }, 437 &typeBool, 438 }, 439 TupleRawNames: []string{"inner", "active"}, 440 }, 441 }, 442 TupleRawNames: []string{"id", "owner", "data", "metadata"}, 443 }, 444 }, 445 { 446 Type: abi.Type{ 447 T: abi.TupleTy, 448 TupleRawName: "arrayStruct", 449 TupleElems: []*abi.Type{ 450 {T: abi.SliceTy, Elem: &typeUint256}, 451 &typeUint256, 452 }, 453 TupleRawNames: []string{"values", "count"}, 454 }, 455 }, 456 }, 457 }, 458 { 459 Input: "@invalid", 460 WantErr: errors.New(`syntax error: unexpected character: @`), 461 }, 462 { 463 Input: "func(uint256 arg0", 464 WantErr: errors.New(`syntax error: unexpected "func", expecting type`), 465 }, 466 { 467 Input: "(:uint256)", 468 WantErr: errors.New(`syntax error: unexpected character: :`), 469 }, 470 { 471 Input: "(uint256 arg0 extra)", 472 WantErr: errors.New(`syntax error: unexpected "extra", expecting "," or ")"`), 473 }, 474 { 475 Input: "(uint256", 476 WantErr: errors.New(`syntax error: unexpected EOF, expecting "," or ")"`), 477 }, 478 { 479 Input: "(uint256 @)", 480 WantErr: errors.New(`syntax error: unexpected character: @`), 481 }, 482 { 483 Input: "uint256 arg0 extra", 484 WantErr: errors.New(`syntax error: unexpected "extra", want "," or EOF`), 485 }, 486 { 487 Input: "uint256 @", 488 WantErr: errors.New(`syntax error: unexpected character: @`), 489 }, 490 { 491 Input: "uint256,@", 492 WantErr: errors.New(`syntax error: unexpected character: @`), 493 }, 494 { 495 Input: "uint256[@", 496 WantErr: errors.New(`syntax error: unexpected character: @`), 497 }, 498 { 499 Input: "nonStruct", 500 Tuples: []any{123}, 501 WantErr: errors.New(`syntax error: expected struct, got int`), 502 }, 503 { 504 Input: "stringType", 505 Tuples: []any{"hello"}, 506 WantErr: errors.New(`syntax error: expected struct, got string`), 507 }, 508 { 509 Input: "structWithInvalidField", 510 Tuples: []any{structWithInvalidField{}}, 511 WantErr: errors.New(`syntax error: unknown type "func()"`), 512 }, 513 } 514 515 for i, test := range tests { 516 t.Run(fmt.Sprintf("%d_%s", i, test.Input), func(t *testing.T) { 517 gotArgs, gotErr := Parse(test.Input, test.Tuples...) 518 if diff := cmp.Diff(test.WantErr, gotErr, 519 internal.EquateErrors(), 520 ); diff != "" { 521 t.Fatalf("Err (-want, +got):\n%s", diff) 522 } 523 if diff := cmp.Diff(test.WantArgs, gotArgs, 524 cmpopts.EquateEmpty(), 525 cmpopts.IgnoreUnexported(abi.Type{}), 526 cmpopts.IgnoreFields(abi.Type{}, "TupleType")); diff != "" { 527 t.Errorf("Args (-want, +got):\n%s", diff) 528 } 529 }) 530 } 531 } 532 533 func TestParseArgsWithName(t *testing.T) { 534 tests := []struct { 535 Input string 536 Tuples []any 537 WantArgs Arguments 538 WantName string 539 WantErr error 540 }{ 541 { 542 Input: "", 543 WantErr: errors.New(`syntax error: unexpected EOF, expecting name`), 544 }, 545 { 546 Input: "uint", 547 WantErr: errors.New(`syntax error: unexpected EOF, expecting "("`), 548 }, 549 { 550 Input: "f()", 551 WantName: "f", 552 }, 553 { 554 Input: "f(", 555 WantErr: errors.New(`syntax error: unexpected EOF, expecting type`), 556 }, 557 { 558 Input: "f(uint256", 559 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 560 }, 561 { 562 Input: "f(uint256 indexed", 563 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 564 }, 565 { 566 Input: "f(uint256 arg0", 567 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 568 }, 569 { 570 Input: "f(uint256 indexed arg0", 571 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 572 }, 573 { 574 Input: "f(uint256,", 575 WantErr: errors.New(`syntax error: unexpected EOF, expecting type`), 576 }, 577 { 578 Input: "transfer(address,uint256)", 579 WantArgs: Arguments{{Type: typeAddress}, {Type: typeUint256}}, 580 WantName: "transfer", 581 }, 582 { 583 Input: "transfer(address recipient, uint256 amount)", 584 WantArgs: Arguments{{Type: typeAddress, Name: "recipient"}, {Type: typeUint256, Name: "amount"}}, 585 WantName: "transfer", 586 }, 587 { 588 Input: "exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params)", 589 WantArgs: Arguments{{ 590 Type: abi.Type{ 591 T: abi.TupleTy, 592 TupleElems: []*abi.Type{&typeAddress, &typeAddress, &typeUint24, &typeAddress, &typeUint256, &typeUint256, &typeUint256, &typeUint160}, 593 TupleRawNames: []string{"tokenIn", "tokenOut", "fee", "recipient", "deadline", "amountIn", "amountOutMinimum", "sqrtPriceLimitX96"}, 594 }, 595 Name: "params", 596 }}, 597 WantName: "exactInputSingle", 598 }, 599 { 600 Input: "transfer(simpleStruct)", 601 Tuples: []any{simpleStruct{}}, 602 WantName: "transfer", 603 WantArgs: Arguments{{ 604 Type: abi.Type{ 605 T: abi.TupleTy, 606 TupleRawName: "simpleStruct", 607 TupleElems: []*abi.Type{&typeUint256, &typeAddress}, 608 TupleRawNames: []string{"amount", "token"}, 609 }, 610 }}, 611 }, 612 // Test cases for error paths in ParseWithName 613 { 614 Input: "f(uint256) extra", 615 WantErr: errors.New(`syntax error: unexpected "extra", expecting EOF`), 616 }, 617 { 618 Input: "f(uint256,", 619 WantErr: errors.New(`syntax error: unexpected EOF, expecting type`), 620 }, 621 { 622 Input: "f(uint256 arg0", 623 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 624 }, 625 { 626 Input: "f(uint256 indexed arg0", 627 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 628 }, 629 { 630 Input: "f((uint256", 631 WantErr: errors.New(`syntax error: unexpected EOF, expecting "," or ")"`), 632 }, 633 { 634 Input: "f(uint256 extra", 635 WantErr: errors.New(`syntax error: unexpected EOF, want "," or ")"`), 636 }, 637 } 638 639 for i, test := range tests { 640 t.Run(fmt.Sprintf("%d_%s", i, test.Input), func(t *testing.T) { 641 gotName, gotArgs, gotErr := ParseWithName(test.Input, test.Tuples...) 642 if diff := cmp.Diff(test.WantErr, gotErr, 643 internal.EquateErrors(), 644 ); diff != "" { 645 t.Fatalf("Err (-want, +got):\n%s", diff) 646 } 647 if test.WantName != gotName { 648 t.Errorf("Name want: %s, got: %s", test.WantName, gotName) 649 } 650 if diff := cmp.Diff(test.WantArgs, gotArgs, 651 cmpopts.EquateEmpty(), 652 cmpopts.IgnoreUnexported(abi.Type{}), 653 cmpopts.IgnoreFields(abi.Type{}, "TupleType")); diff != "" { 654 t.Errorf("Args (-want, +got):\n%s", diff) 655 } 656 }) 657 } 658 } 659 660 func BenchmarkParseArgsWithName(b *testing.B) { 661 benchmarks := []struct { 662 Name string 663 Input string 664 }{ 665 {Name: "symbol", Input: "symbol()"}, 666 {Name: "transfer", Input: "transfer(address,uint256)"}, 667 {Name: "exactInputSingle", Input: "exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params)"}, 668 {Name: "swap", Input: `swap( 669 (address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks) key, 670 (bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96) params, 671 bytes hookData 672 )`}, 673 {Name: "settle", Input: `settle( 674 address[] tokens, 675 uint256[] clearingPrices, 676 ( 677 uint256 sellTokenIndex, 678 uint256 buyTokenIndex, 679 address receiver, 680 uint256 sellAmount, 681 uint256 buyAmount, 682 uint32 validTo, 683 bytes32 appData, 684 uint256 feeAmount, 685 uint256 flags, 686 uint256 executedAmount, 687 bytes signature 688 )[] trades, 689 (address target, uint256 value, bytes callData)[][3] interactions 690 )`}, 691 } 692 693 for _, bench := range benchmarks { 694 b.Run(bench.Name, func(b *testing.B) { 695 b.ReportAllocs() 696 for range b.N { 697 ParseWithName(bench.Input) 698 } 699 }) 700 } 701 } 702 703 // test structs for tuple functionality 704 type simpleStruct struct { 705 Amount *big.Int `abitype:"uint256"` 706 Token common.Address `abitype:"address"` 707 } 708 709 type simpleStructWithoutTags struct { 710 Amount *big.Int 711 Token common.Address 712 } 713 714 type nestedStruct struct { 715 Inner simpleStruct 716 Active bool 717 } 718 719 type complexStruct struct { 720 ID *big.Int `abitype:"uint256"` 721 Owner common.Address 722 Data []byte 723 Metadata nestedStruct 724 } 725 726 type arrayStruct struct { 727 Values []*big.Int `abitype:"uint256"` 728 Count *big.Int `abitype:"uint256"` 729 } 730 731 type emptyStruct struct{} 732 733 // Test struct with invalid field type for coverage 734 type structWithInvalidField struct { 735 InvalidFunc func() // This will cause typeOf to fail 736 }