github.com/dim4egster/coreth@v0.10.2/accounts/abi/bind/base_test.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2019 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package bind_test 28 29 import ( 30 "context" 31 "errors" 32 "fmt" 33 "math/big" 34 "reflect" 35 "strings" 36 "testing" 37 38 "github.com/dim4egster/coreth/accounts/abi" 39 "github.com/dim4egster/coreth/accounts/abi/bind" 40 "github.com/dim4egster/coreth/core/types" 41 "github.com/dim4egster/coreth/core/vm" 42 "github.com/dim4egster/coreth/interfaces" 43 "github.com/ethereum/go-ethereum/common" 44 "github.com/ethereum/go-ethereum/common/hexutil" 45 "github.com/ethereum/go-ethereum/crypto" 46 "github.com/ethereum/go-ethereum/rlp" 47 "github.com/stretchr/testify/assert" 48 ) 49 50 func mockSign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return tx, nil } 51 52 type mockTransactor struct { 53 baseFee *big.Int 54 gasTipCap *big.Int 55 gasPrice *big.Int 56 suggestGasTipCapCalled bool 57 suggestGasPriceCalled bool 58 } 59 60 func (mt *mockTransactor) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 61 return &types.Header{BaseFee: mt.baseFee}, nil 62 } 63 64 func (mt *mockTransactor) AcceptedCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 65 return []byte{1}, nil 66 } 67 68 func (mt *mockTransactor) AcceptedNonceAt(ctx context.Context, account common.Address) (uint64, error) { 69 return 0, nil 70 } 71 72 func (mt *mockTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 73 mt.suggestGasPriceCalled = true 74 return mt.gasPrice, nil 75 } 76 77 func (mt *mockTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 78 mt.suggestGasTipCapCalled = true 79 return mt.gasTipCap, nil 80 } 81 82 func (mt *mockTransactor) EstimateGas(ctx context.Context, call interfaces.CallMsg) (gas uint64, err error) { 83 return 0, nil 84 } 85 86 func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error { 87 return nil 88 } 89 90 type mockCaller struct { 91 codeAtBlockNumber *big.Int 92 callContractBlockNumber *big.Int 93 callContractBytes []byte 94 callContractErr error 95 codeAtBytes []byte 96 codeAtErr error 97 } 98 99 func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 100 mc.codeAtBlockNumber = blockNumber 101 return mc.codeAtBytes, mc.codeAtErr 102 } 103 104 func (mc *mockCaller) CallContract(ctx context.Context, call interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) { 105 mc.callContractBlockNumber = blockNumber 106 return mc.callContractBytes, mc.callContractErr 107 } 108 109 type mockAcceptedCaller struct { 110 *mockCaller 111 acceptedCodeAtBytes []byte 112 acceptedCodeAtErr error 113 acceptedCodeAtCalled bool 114 acceptedCallContractCalled bool 115 acceptedCallContractBytes []byte 116 acceptedCallContractErr error 117 } 118 119 func (mc *mockAcceptedCaller) AcceptedCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { 120 mc.acceptedCodeAtCalled = true 121 return mc.acceptedCodeAtBytes, mc.acceptedCodeAtErr 122 } 123 124 func (mc *mockAcceptedCaller) AcceptedCallContract(ctx context.Context, call interfaces.CallMsg) ([]byte, error) { 125 mc.acceptedCallContractCalled = true 126 return mc.acceptedCallContractBytes, mc.acceptedCallContractErr 127 } 128 func TestPassingBlockNumber(t *testing.T) { 129 mc := &mockAcceptedCaller{ 130 mockCaller: &mockCaller{ 131 codeAtBytes: []byte{1, 2, 3}, 132 }, 133 } 134 135 bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ 136 Methods: map[string]abi.Method{ 137 "something": { 138 Name: "something", 139 Outputs: abi.Arguments{}, 140 }, 141 }, 142 }, mc, nil, nil) 143 144 blockNumber := big.NewInt(42) 145 146 bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something") 147 148 if mc.callContractBlockNumber != blockNumber { 149 t.Fatalf("CallContract() was not passed the block number") 150 } 151 152 if mc.codeAtBlockNumber != blockNumber { 153 t.Fatalf("CodeAt() was not passed the block number") 154 } 155 156 bc.Call(&bind.CallOpts{}, nil, "something") 157 158 if mc.callContractBlockNumber != nil { 159 t.Fatalf("CallContract() was passed a block number when it should not have been") 160 } 161 162 if mc.codeAtBlockNumber != nil { 163 t.Fatalf("CodeAt() was passed a block number when it should not have been") 164 } 165 166 bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Accepted: true}, nil, "something") 167 168 if !mc.acceptedCallContractCalled { 169 t.Fatalf("CallContract() was not passed the block number") 170 } 171 172 if !mc.acceptedCodeAtCalled { 173 t.Fatalf("CodeAt() was not passed the block number") 174 } 175 } 176 177 const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158" 178 179 func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) { 180 hash := crypto.Keccak256Hash([]byte("testName")) 181 topics := []common.Hash{ 182 crypto.Keccak256Hash([]byte("received(string,address,uint256,bytes)")), 183 hash, 184 } 185 mockLog := newMockLog(topics, common.HexToHash("0x0")) 186 187 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 188 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 189 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 190 191 expectedReceivedMap := map[string]interface{}{ 192 "name": hash, 193 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 194 "amount": big.NewInt(1), 195 "memo": []byte{88}, 196 } 197 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 198 } 199 200 func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) { 201 sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"}) 202 if err != nil { 203 t.Fatal(err) 204 } 205 hash := crypto.Keccak256Hash(sliceBytes) 206 topics := []common.Hash{ 207 crypto.Keccak256Hash([]byte("received(string[],address,uint256,bytes)")), 208 hash, 209 } 210 mockLog := newMockLog(topics, common.HexToHash("0x0")) 211 212 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 213 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 214 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 215 216 expectedReceivedMap := map[string]interface{}{ 217 "names": hash, 218 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 219 "amount": big.NewInt(1), 220 "memo": []byte{88}, 221 } 222 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 223 } 224 225 func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) { 226 arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")}) 227 if err != nil { 228 t.Fatal(err) 229 } 230 hash := crypto.Keccak256Hash(arrBytes) 231 topics := []common.Hash{ 232 crypto.Keccak256Hash([]byte("received(address[2],address,uint256,bytes)")), 233 hash, 234 } 235 mockLog := newMockLog(topics, common.HexToHash("0x0")) 236 237 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 238 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 239 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 240 241 expectedReceivedMap := map[string]interface{}{ 242 "addresses": hash, 243 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 244 "amount": big.NewInt(1), 245 "memo": []byte{88}, 246 } 247 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 248 } 249 250 func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) { 251 mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2") 252 addrBytes := mockAddress.Bytes() 253 hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)")) 254 functionSelector := hash[:4] 255 functionTyBytes := append(addrBytes, functionSelector...) 256 var functionTy [24]byte 257 copy(functionTy[:], functionTyBytes[0:24]) 258 topics := []common.Hash{ 259 crypto.Keccak256Hash([]byte("received(function,address,uint256,bytes)")), 260 common.BytesToHash(functionTyBytes), 261 } 262 mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) 263 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 264 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 265 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 266 267 expectedReceivedMap := map[string]interface{}{ 268 "function": functionTy, 269 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 270 "amount": big.NewInt(1), 271 "memo": []byte{88}, 272 } 273 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 274 } 275 276 func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) { 277 bytes := []byte{1, 2, 3, 4, 5} 278 hash := crypto.Keccak256Hash(bytes) 279 topics := []common.Hash{ 280 crypto.Keccak256Hash([]byte("received(bytes,address,uint256,bytes)")), 281 hash, 282 } 283 mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) 284 285 abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` 286 parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) 287 bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) 288 289 expectedReceivedMap := map[string]interface{}{ 290 "content": hash, 291 "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), 292 "amount": big.NewInt(1), 293 "memo": []byte{88}, 294 } 295 unpackAndCheck(t, bc, expectedReceivedMap, mockLog) 296 } 297 298 func TestTransactNativeAssetCallNilAssetAmount(t *testing.T) { 299 assert := assert.New(t) 300 mt := &mockTransactor{} 301 bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) 302 opts := &bind.TransactOpts{ 303 Signer: mockSign, 304 } 305 // fails if asset amount is nil 306 opts.NativeAssetCall = &bind.NativeAssetCallOpts{ 307 AssetID: common.Hash{}, 308 AssetAmount: nil, 309 } 310 _, err := bc.Transact(opts, "") 311 assert.ErrorIs(err, bind.ErrNilAssetAmount) 312 } 313 314 func TestTransactNativeAssetCallNonZeroValue(t *testing.T) { 315 assert := assert.New(t) 316 mt := &mockTransactor{} 317 bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) 318 opts := &bind.TransactOpts{ 319 Signer: mockSign, 320 } 321 opts.NativeAssetCall = &bind.NativeAssetCallOpts{ 322 AssetID: common.Hash{}, 323 AssetAmount: big.NewInt(11), 324 } 325 // fails if value > 0 326 opts.Value = big.NewInt(11) 327 _, err := bc.Transact(opts, "") 328 assert.Equal(err.Error(), fmt.Sprintf("value must be 0 when performing native asset call, found %v", opts.Value)) 329 // fails if value < 0 330 opts.Value = big.NewInt(-11) 331 _, err = bc.Transact(opts, "") 332 assert.Equal(err.Error(), fmt.Sprintf("value must be 0 when performing native asset call, found %v", opts.Value)) 333 } 334 335 func TestTransactNativeAssetCall(t *testing.T) { 336 assert := assert.New(t) 337 json := `[{"type":"function","name":"method","inputs":[{"type":"uint256" },{"type":"string"}]}]` 338 parsed, err := abi.JSON(strings.NewReader(json)) 339 assert.Nil(err) 340 mt := &mockTransactor{} 341 contractAddr := common.Address{11} 342 bc := bind.NewBoundContract(contractAddr, parsed, nil, mt, nil) 343 opts := &bind.TransactOpts{ 344 Signer: mockSign, 345 } 346 // normal call tx 347 methodName := "method" 348 arg1 := big.NewInt(22) 349 arg2 := "33" 350 normalCallTx, err := bc.Transact(opts, methodName, arg1, arg2) 351 assert.Nil(err) 352 // native asset call tx 353 assetID := common.Hash{44} 354 assetAmount := big.NewInt(55) 355 opts.NativeAssetCall = &bind.NativeAssetCallOpts{ 356 AssetID: assetID, 357 AssetAmount: assetAmount, 358 } 359 nativeCallTx, err := bc.Transact(opts, methodName, arg1, arg2) 360 assert.Nil(err) 361 // verify transformations 362 assert.Equal(vm.NativeAssetCallAddr, *nativeCallTx.To()) 363 unpackedAddr, unpackedAssetID, unpackedAssetAmount, unpackedData, err := vm.UnpackNativeAssetCallInput(nativeCallTx.Data()) 364 assert.Nil(err) 365 assert.NotEmpty(unpackedData) 366 assert.Equal(unpackedData, normalCallTx.Data()) 367 assert.Equal(unpackedAddr, contractAddr) 368 assert.Equal(unpackedAssetID, assetID) 369 assert.Equal(unpackedAssetAmount, assetAmount) 370 } 371 372 func TestTransactGasFee(t *testing.T) { 373 assert := assert.New(t) 374 375 // GasTipCap and GasFeeCap 376 // When opts.GasTipCap and opts.GasFeeCap are nil 377 mt := &mockTransactor{baseFee: big.NewInt(100), gasTipCap: big.NewInt(5)} 378 bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) 379 opts := &bind.TransactOpts{Signer: mockSign} 380 tx, err := bc.Transact(opts, "") 381 assert.Nil(err) 382 assert.Equal(big.NewInt(5), tx.GasTipCap()) 383 assert.Equal(big.NewInt(205), tx.GasFeeCap()) 384 assert.Nil(opts.GasTipCap) 385 assert.Nil(opts.GasFeeCap) 386 assert.True(mt.suggestGasTipCapCalled) 387 388 // Second call to Transact should use latest suggested GasTipCap 389 mt.gasTipCap = big.NewInt(6) 390 mt.suggestGasTipCapCalled = false 391 tx, err = bc.Transact(opts, "") 392 assert.Nil(err) 393 assert.Equal(big.NewInt(6), tx.GasTipCap()) 394 assert.Equal(big.NewInt(206), tx.GasFeeCap()) 395 assert.True(mt.suggestGasTipCapCalled) 396 397 // GasPrice 398 // When opts.GasPrice is nil 399 mt = &mockTransactor{gasPrice: big.NewInt(5)} 400 bc = bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) 401 opts = &bind.TransactOpts{Signer: mockSign} 402 tx, err = bc.Transact(opts, "") 403 assert.Nil(err) 404 assert.Equal(big.NewInt(5), tx.GasPrice()) 405 assert.Nil(opts.GasPrice) 406 assert.True(mt.suggestGasPriceCalled) 407 408 // Second call to Transact should use latest suggested GasPrice 409 mt.gasPrice = big.NewInt(6) 410 mt.suggestGasPriceCalled = false 411 tx, err = bc.Transact(opts, "") 412 assert.Nil(err) 413 assert.Equal(big.NewInt(6), tx.GasPrice()) 414 assert.True(mt.suggestGasPriceCalled) 415 } 416 417 func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) { 418 received := make(map[string]interface{}) 419 if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil { 420 t.Error(err) 421 } 422 423 if len(received) != len(expected) { 424 t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected)) 425 } 426 for name, elem := range expected { 427 if !reflect.DeepEqual(elem, received[name]) { 428 t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name]) 429 } 430 } 431 } 432 433 func newMockLog(topics []common.Hash, txHash common.Hash) types.Log { 434 return types.Log{ 435 Address: common.HexToAddress("0x0"), 436 Topics: topics, 437 Data: hexutil.MustDecode(hexData), 438 BlockNumber: uint64(26), 439 TxHash: txHash, 440 TxIndex: 111, 441 BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), 442 Index: 7, 443 Removed: false, 444 } 445 } 446 447 func TestCall(t *testing.T) { 448 var method, methodWithArg = "something", "somethingArrrrg" 449 tests := []struct { 450 name, method string 451 opts *bind.CallOpts 452 mc bind.ContractCaller 453 results *[]interface{} 454 wantErr bool 455 wantErrExact error 456 }{{ 457 name: "ok not accepted", 458 mc: &mockCaller{ 459 codeAtBytes: []byte{0}, 460 }, 461 method: method, 462 }, { 463 name: "ok accepted", 464 mc: &mockAcceptedCaller{ 465 acceptedCodeAtBytes: []byte{0}, 466 }, 467 opts: &bind.CallOpts{ 468 Accepted: true, 469 }, 470 method: method, 471 }, { 472 name: "pack error, no method", 473 mc: new(mockCaller), 474 method: "else", 475 wantErr: true, 476 }, { 477 name: "interface error, accepted but not a AcceptedContractCaller", 478 mc: new(mockCaller), 479 opts: &bind.CallOpts{ 480 Accepted: true, 481 }, 482 method: method, 483 wantErrExact: bind.ErrNoAcceptedState, 484 }, { 485 name: "accepted call canceled", 486 mc: &mockAcceptedCaller{ 487 acceptedCallContractErr: context.DeadlineExceeded, 488 }, 489 opts: &bind.CallOpts{ 490 Accepted: true, 491 }, 492 method: method, 493 wantErrExact: context.DeadlineExceeded, 494 }, { 495 name: "accepted code at error", 496 mc: &mockAcceptedCaller{ 497 acceptedCodeAtErr: errors.New(""), 498 }, 499 opts: &bind.CallOpts{ 500 Accepted: true, 501 }, 502 method: method, 503 wantErr: true, 504 }, { 505 name: "no accepted code at", 506 mc: new(mockAcceptedCaller), 507 opts: &bind.CallOpts{ 508 Accepted: true, 509 }, 510 method: method, 511 wantErrExact: bind.ErrNoCode, 512 }, { 513 name: "call contract error", 514 mc: &mockCaller{ 515 callContractErr: context.DeadlineExceeded, 516 }, 517 method: method, 518 wantErrExact: context.DeadlineExceeded, 519 }, { 520 name: "code at error", 521 mc: &mockCaller{ 522 codeAtErr: errors.New(""), 523 }, 524 method: method, 525 wantErr: true, 526 }, { 527 name: "no code at", 528 mc: new(mockCaller), 529 method: method, 530 wantErrExact: bind.ErrNoCode, 531 }, { 532 name: "unpack error missing arg", 533 mc: &mockCaller{ 534 codeAtBytes: []byte{0}, 535 }, 536 method: methodWithArg, 537 wantErr: true, 538 }, { 539 name: "interface unpack error", 540 mc: &mockCaller{ 541 codeAtBytes: []byte{0}, 542 }, 543 method: method, 544 results: &[]interface{}{0}, 545 wantErr: true, 546 }} 547 for _, test := range tests { 548 bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ 549 Methods: map[string]abi.Method{ 550 method: { 551 Name: method, 552 Outputs: abi.Arguments{}, 553 }, 554 methodWithArg: { 555 Name: methodWithArg, 556 Outputs: abi.Arguments{abi.Argument{}}, 557 }, 558 }, 559 }, test.mc, nil, nil) 560 err := bc.Call(test.opts, test.results, test.method) 561 if test.wantErr || test.wantErrExact != nil { 562 if err == nil { 563 t.Fatalf("%q expected error", test.name) 564 } 565 if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) { 566 t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err) 567 } 568 continue 569 } 570 if err != nil { 571 t.Fatalf("%q unexpected error: %v", test.name, err) 572 } 573 } 574 } 575 576 // TestCrashers contains some strings which previously caused the abi codec to crash. 577 func TestCrashers(t *testing.T) { 578 abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`)) 579 abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`)) 580 abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`)) 581 abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"foo.Bar"}]}]}]`)) 582 }