github.com/ethersphere/bee/v2@v2.2.0/pkg/storageincentives/staking/contract_test.go (about) 1 // Copyright 2022 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package staking_test 6 7 import ( 8 "bytes" 9 "context" 10 "errors" 11 "fmt" 12 "math/big" 13 "strings" 14 "testing" 15 16 "github.com/ethereum/go-ethereum/common" 17 "github.com/ethereum/go-ethereum/core/types" 18 chaincfg "github.com/ethersphere/bee/v2/pkg/config" 19 "github.com/ethersphere/bee/v2/pkg/storageincentives/staking" 20 "github.com/ethersphere/bee/v2/pkg/swarm" 21 "github.com/ethersphere/bee/v2/pkg/transaction" 22 transactionMock "github.com/ethersphere/bee/v2/pkg/transaction/mock" 23 "github.com/ethersphere/bee/v2/pkg/util/abiutil" 24 ) 25 26 var stakingContractABI = abiutil.MustParseABI(chaincfg.Testnet.StakingABI) 27 28 func TestIsOverlayFrozen(t *testing.T) { 29 t.Parallel() 30 31 ctx := context.Background() 32 owner := common.HexToAddress("abcd") 33 stakingContractAddress := common.HexToAddress("ffff") 34 bzzTokenAddress := common.HexToAddress("eeee") 35 nonce := common.BytesToHash(make([]byte, 32)) 36 37 height := 100 38 frozenHeight := big.NewInt(int64(height)) 39 40 t.Run("ok", func(t *testing.T) { 41 t.Parallel() 42 43 contract := staking.New( 44 owner, 45 stakingContractAddress, 46 stakingContractABI, 47 bzzTokenAddress, 48 transactionMock.New( 49 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 50 if *request.To == stakingContractAddress { 51 return frozenHeight.FillBytes(make([]byte, 32)), nil 52 } 53 return nil, errors.New("unexpected call") 54 }), 55 ), 56 nonce, 57 false, 58 ) 59 60 frozen, err := contract.IsOverlayFrozen(ctx, uint64(height-1)) 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 if !frozen { 66 t.Fatalf("expected owner to be frozen") 67 } 68 69 frozen, err = contract.IsOverlayFrozen(ctx, uint64(height+1)) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 if frozen { 75 t.Fatalf("expected owner to not be frozen") 76 } 77 78 }) 79 } 80 81 func TestDepositStake(t *testing.T) { 82 t.Parallel() 83 84 ctx := context.Background() 85 owner := common.HexToAddress("abcd") 86 stakingContractAddress := common.HexToAddress("ffff") 87 bzzTokenAddress := common.HexToAddress("eeee") 88 nonce := common.BytesToHash(make([]byte, 32)) 89 txHashDeposited := common.HexToHash("c3a7") 90 stakedAmount := big.NewInt(100000000000000000) 91 txHashApprove := common.HexToHash("abb0") 92 93 t.Run("ok", func(t *testing.T) { 94 t.Parallel() 95 96 totalAmount := big.NewInt(100000000000000000) 97 prevStake := big.NewInt(0) 98 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, stakedAmount) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 contract := staking.New( 104 owner, 105 stakingContractAddress, 106 stakingContractABI, 107 bzzTokenAddress, 108 transactionMock.New( 109 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 110 if *request.To == bzzTokenAddress { 111 return txHashApprove, nil 112 } 113 if *request.To == stakingContractAddress { 114 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 115 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 116 } 117 return txHashDeposited, nil 118 } 119 return common.Hash{}, errors.New("sent to wrong contract") 120 }), 121 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 122 if txHash == txHashDeposited { 123 return &types.Receipt{ 124 Status: 1, 125 }, nil 126 } 127 if txHash == txHashApprove { 128 return &types.Receipt{ 129 Status: 1, 130 }, nil 131 } 132 return nil, errors.New("unknown tx hash") 133 }), 134 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 135 if *request.To == bzzTokenAddress { 136 return totalAmount.FillBytes(make([]byte, 32)), nil 137 } 138 if *request.To == stakingContractAddress { 139 return getPotentialStakeResponse(t, prevStake), nil 140 } 141 return nil, errors.New("unexpected call") 142 }), 143 ), 144 nonce, 145 false, 146 ) 147 148 _, err = contract.DepositStake(ctx, stakedAmount) 149 if err != nil { 150 t.Fatal(err) 151 } 152 }) 153 154 t.Run("ok with addon stake", func(t *testing.T) { 155 t.Parallel() 156 157 totalAmount := big.NewInt(100000000000000000) 158 prevStake := big.NewInt(2) 159 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, big.NewInt(100000000000000000)) 160 if err != nil { 161 t.Fatal(err) 162 } 163 164 contract := staking.New( 165 owner, 166 stakingContractAddress, 167 stakingContractABI, 168 bzzTokenAddress, 169 transactionMock.New( 170 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 171 if *request.To == bzzTokenAddress { 172 return txHashApprove, nil 173 } 174 if *request.To == stakingContractAddress { 175 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 176 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 177 } 178 return txHashDeposited, nil 179 } 180 return common.Hash{}, errors.New("sent to wrong contract") 181 }), 182 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 183 if txHash == txHashDeposited { 184 return &types.Receipt{ 185 Status: 1, 186 }, nil 187 } 188 if txHash == txHashApprove { 189 return &types.Receipt{ 190 Status: 1, 191 }, nil 192 } 193 return nil, errors.New("unknown tx hash") 194 }), 195 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 196 if *request.To == bzzTokenAddress { 197 return totalAmount.FillBytes(make([]byte, 32)), nil 198 } 199 if *request.To == stakingContractAddress { 200 return getPotentialStakeResponse(t, prevStake), nil 201 } 202 return nil, errors.New("unexpected call") 203 }), 204 ), 205 nonce, 206 false, 207 ) 208 209 _, err = contract.DepositStake(ctx, stakedAmount) 210 if err != nil { 211 t.Fatal(err) 212 } 213 stakedAmount, err := contract.GetPotentialStake(ctx) 214 if err != nil { 215 t.Fatal(err) 216 } 217 if stakedAmount.Cmp(big.NewInt(13)) == 0 { 218 t.Fatalf("expected %v, got %v", big.NewInt(13), stakedAmount) 219 } 220 }) 221 222 t.Run("insufficient stake amount", func(t *testing.T) { 223 t.Parallel() 224 225 totalAmount := big.NewInt(102400) 226 prevStake := big.NewInt(0) 227 228 contract := staking.New( 229 owner, 230 stakingContractAddress, 231 stakingContractABI, 232 bzzTokenAddress, 233 transactionMock.New( 234 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 235 if *request.To == bzzTokenAddress { 236 return totalAmount.FillBytes(make([]byte, 32)), nil 237 } 238 if *request.To == stakingContractAddress { 239 return getPotentialStakeResponse(t, prevStake), nil 240 } 241 return nil, errors.New("unexpected call") 242 }), 243 ), 244 nonce, 245 false, 246 ) 247 248 _, err := contract.DepositStake(ctx, big.NewInt(0)) 249 if !errors.Is(err, staking.ErrInsufficientStakeAmount) { 250 t.Fatal(fmt.Errorf("wanted %w, got %w", staking.ErrInsufficientStakeAmount, err)) 251 } 252 }) 253 254 t.Run("insufficient funds", func(t *testing.T) { 255 t.Parallel() 256 257 totalAmount := big.NewInt(0) 258 prevStake := big.NewInt(0) 259 260 contract := staking.New( 261 owner, 262 stakingContractAddress, 263 stakingContractABI, 264 bzzTokenAddress, 265 transactionMock.New( 266 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 267 if *request.To == bzzTokenAddress { 268 return totalAmount.FillBytes(make([]byte, 32)), nil 269 } 270 if *request.To == stakingContractAddress { 271 return getPotentialStakeResponse(t, prevStake), nil 272 } 273 return nil, errors.New("unexpected call") 274 }), 275 ), 276 nonce, 277 false, 278 ) 279 280 _, err := contract.DepositStake(ctx, big.NewInt(100000000000000000)) 281 if !errors.Is(err, staking.ErrInsufficientFunds) { 282 t.Fatal(fmt.Errorf("wanted %w, got %w", staking.ErrInsufficientFunds, err)) 283 } 284 }) 285 286 t.Run("insufficient stake amount", func(t *testing.T) { 287 t.Parallel() 288 289 totalAmount := big.NewInt(0) 290 prevStake := big.NewInt(0) 291 292 contract := staking.New( 293 owner, 294 stakingContractAddress, 295 stakingContractABI, 296 bzzTokenAddress, 297 transactionMock.New( 298 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 299 if *request.To == bzzTokenAddress { 300 return totalAmount.FillBytes(make([]byte, 32)), nil 301 } 302 if *request.To == stakingContractAddress { 303 return getPotentialStakeResponse(t, prevStake), nil 304 } 305 return nil, errors.New("unexpected call") 306 }), 307 ), 308 nonce, 309 false, 310 ) 311 312 _, err := contract.DepositStake(ctx, big.NewInt(100000000000000000)) 313 if !errors.Is(err, staking.ErrInsufficientFunds) { 314 t.Fatal(fmt.Errorf("wanted %w, got %w", staking.ErrInsufficientStakeAmount, err)) 315 } 316 }) 317 318 t.Run("send tx failed", func(t *testing.T) { 319 t.Parallel() 320 321 totalAmount := big.NewInt(102400) 322 prevStake := big.NewInt(0) 323 324 contract := staking.New( 325 owner, 326 stakingContractAddress, 327 stakingContractABI, 328 bzzTokenAddress, 329 transactionMock.New( 330 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 331 if *request.To == bzzTokenAddress { 332 return common.Hash{}, errors.New("send transaction failed") 333 } 334 return common.Hash{}, errors.New("sent to wrong contract") 335 }), 336 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 337 if *request.To == bzzTokenAddress { 338 return totalAmount.FillBytes(make([]byte, 32)), nil 339 } 340 if *request.To == stakingContractAddress { 341 return prevStake.FillBytes(make([]byte, 32)), nil 342 } 343 return nil, errors.New("unexpected call") 344 }), 345 ), 346 nonce, 347 false, 348 ) 349 350 _, err := contract.DepositStake(ctx, stakedAmount) 351 if err == nil { 352 t.Fatal("expected error") 353 } 354 }) 355 356 t.Run("invalid call data", func(t *testing.T) { 357 t.Parallel() 358 359 totalAmount := big.NewInt(102400) 360 prevStake := big.NewInt(0) 361 expectedStakeAmount := big.NewInt(100) 362 expectedCallData, err := staking.Erc20ABI.Pack("approve", stakingContractAddress, expectedStakeAmount) 363 if err != nil { 364 t.Fatal(err) 365 } 366 367 contract := staking.New( 368 owner, 369 stakingContractAddress, 370 stakingContractABI, 371 bzzTokenAddress, 372 transactionMock.New( 373 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 374 if *request.To == bzzTokenAddress { 375 if !bytes.Equal(expectedCallData[:], request.Data[:]) { 376 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 377 } 378 return txHashApprove, nil 379 } 380 if *request.To == stakingContractAddress { 381 return txHashDeposited, nil 382 } 383 return common.Hash{}, errors.New("sent to wrong contract") 384 }), 385 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 386 if *request.To == bzzTokenAddress { 387 return totalAmount.FillBytes(make([]byte, 32)), nil 388 } 389 if *request.To == stakingContractAddress { 390 return prevStake.FillBytes(make([]byte, 32)), nil 391 } 392 return nil, errors.New("unexpected call") 393 }), 394 ), 395 nonce, 396 false, 397 ) 398 399 _, err = contract.DepositStake(ctx, stakedAmount) 400 if err == nil { 401 t.Fatal("expected error") 402 } 403 }) 404 405 t.Run("transaction reverted", func(t *testing.T) { 406 t.Parallel() 407 408 totalAmount := big.NewInt(100000000000000000) 409 prevStake := big.NewInt(0) 410 expectedCallData, err := staking.Erc20ABI.Pack("approve", stakingContractAddress, stakedAmount) 411 if err != nil { 412 t.Fatal(err) 413 } 414 415 contract := staking.New( 416 owner, 417 stakingContractAddress, 418 stakingContractABI, 419 bzzTokenAddress, 420 transactionMock.New( 421 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 422 if *request.To == bzzTokenAddress { 423 return txHashApprove, nil 424 } 425 if *request.To == stakingContractAddress { 426 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 427 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 428 } 429 return txHashDeposited, nil 430 } 431 return txHashDeposited, errors.New("sent to wrong contract") 432 }), 433 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 434 if txHash == txHashDeposited { 435 return &types.Receipt{ 436 Status: 1, 437 }, nil 438 } 439 if txHash == txHashApprove { 440 return &types.Receipt{ 441 Status: 0, 442 }, nil 443 } 444 return nil, errors.New("unknown tx hash") 445 }), 446 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 447 if *request.To == bzzTokenAddress { 448 return totalAmount.FillBytes(make([]byte, 32)), nil 449 } 450 if *request.To == stakingContractAddress { 451 return getPotentialStakeResponse(t, prevStake), nil 452 453 } 454 return nil, errors.New("unexpected call") 455 }), 456 ), 457 nonce, 458 false, 459 ) 460 461 _, err = contract.DepositStake(ctx, stakedAmount) 462 if !errors.Is(err, transaction.ErrTransactionReverted) { 463 t.Fatalf("expected %v, got %v", transaction.ErrTransactionReverted, err) 464 } 465 }) 466 467 t.Run("transaction error", func(t *testing.T) { 468 t.Parallel() 469 470 totalAmount := big.NewInt(102400) 471 prevStake := big.NewInt(0) 472 expectedCallData, err := staking.Erc20ABI.Pack("approve", stakingContractAddress, stakedAmount) 473 if err != nil { 474 t.Fatal(err) 475 } 476 477 contract := staking.New( 478 owner, 479 stakingContractAddress, 480 stakingContractABI, 481 bzzTokenAddress, 482 transactionMock.New( 483 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 484 if *request.To == bzzTokenAddress { 485 return txHashApprove, nil 486 } 487 if *request.To == stakingContractAddress { 488 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 489 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 490 } 491 return txHashDeposited, nil 492 } 493 return common.Hash{}, errors.New("sent to wrong contract") 494 }), 495 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 496 if txHash == txHashDeposited { 497 return &types.Receipt{ 498 Status: 1, 499 }, nil 500 } 501 if txHash == txHashApprove { 502 return nil, fmt.Errorf("unknown error") 503 } 504 return nil, errors.New("unknown tx hash") 505 }), 506 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 507 if *request.To == bzzTokenAddress { 508 return totalAmount.FillBytes(make([]byte, 32)), nil 509 } 510 if *request.To == stakingContractAddress { 511 return getPotentialStakeResponse(t, prevStake), nil 512 513 } 514 return nil, errors.New("unexpected call") 515 }), 516 ), 517 nonce, 518 false, 519 ) 520 521 _, err = contract.DepositStake(ctx, stakedAmount) 522 if err == nil { 523 t.Fatalf("expected error") 524 } 525 }) 526 527 t.Run("transaction error in call", func(t *testing.T) { 528 t.Parallel() 529 530 contract := staking.New( 531 owner, 532 stakingContractAddress, 533 stakingContractABI, 534 bzzTokenAddress, 535 transactionMock.New( 536 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 537 if *request.To == stakingContractAddress { 538 return nil, errors.New("some error") 539 } 540 return nil, errors.New("unexpected call") 541 }), 542 ), 543 nonce, 544 false, 545 ) 546 547 _, err := contract.DepositStake(ctx, stakedAmount) 548 if err == nil { 549 t.Fatalf("expected error") 550 } 551 }) 552 } 553 554 func TestChangeStakeOverlay(t *testing.T) { 555 t.Parallel() 556 557 ctx := context.Background() 558 owner := common.HexToAddress("abcd") 559 stakingContractAddress := common.HexToAddress("ffff") 560 bzzTokenAddress := common.HexToAddress("eeee") 561 nonce := common.BytesToHash(make([]byte, 32)) 562 txHashOverlayChanged := common.HexToHash("c3a7") 563 stakedAmount := big.NewInt(0) 564 txHashApprove := common.HexToHash("abb0") 565 566 t.Run("ok", func(t *testing.T) { 567 t.Parallel() 568 569 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, stakedAmount) 570 if err != nil { 571 t.Fatal(err) 572 } 573 574 contract := staking.New( 575 owner, 576 stakingContractAddress, 577 stakingContractABI, 578 bzzTokenAddress, 579 transactionMock.New( 580 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 581 if *request.To == stakingContractAddress { 582 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 583 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 584 } 585 return txHashOverlayChanged, nil 586 } 587 return common.Hash{}, errors.New("sent to wrong contract") 588 }), 589 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 590 if txHash == txHashOverlayChanged { 591 return &types.Receipt{ 592 Status: 1, 593 }, nil 594 } 595 return nil, errors.New("unknown tx hash") 596 }), 597 ), 598 nonce, 599 false, 600 ) 601 602 _, err = contract.ChangeStakeOverlay(ctx, nonce) 603 if err != nil { 604 t.Fatal(err) 605 } 606 }) 607 608 t.Run("send tx failed", func(t *testing.T) { 609 t.Parallel() 610 611 contract := staking.New( 612 owner, 613 stakingContractAddress, 614 stakingContractABI, 615 bzzTokenAddress, 616 transactionMock.New( 617 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 618 if *request.To == stakingContractAddress { 619 return common.Hash{}, errors.New("send transaction failed") 620 } 621 return common.Hash{}, errors.New("sent to wrong contract") 622 }), 623 ), 624 nonce, 625 false, 626 ) 627 628 _, err := contract.ChangeStakeOverlay(ctx, nonce) 629 if err == nil || !strings.Contains(err.Error(), "send transaction failed") { 630 t.Fatal("expected different error") 631 } 632 }) 633 634 t.Run("invalid call data", func(t *testing.T) { 635 t.Parallel() 636 637 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, stakedAmount) 638 if err != nil { 639 t.Fatal(err) 640 } 641 642 contract := staking.New( 643 owner, 644 stakingContractAddress, 645 stakingContractABI, 646 bzzTokenAddress, 647 transactionMock.New( 648 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 649 if *request.To == stakingContractAddress { 650 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 651 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 652 } 653 return txHashApprove, nil 654 } 655 return common.Hash{}, errors.New("sent to wrong contract") 656 }), 657 ), 658 nonce, 659 false, 660 ) 661 662 newNonce := make([]byte, 32) 663 copy(newNonce, nonce[:]) 664 newNonce[0]++ 665 _, err = contract.ChangeStakeOverlay(ctx, common.BytesToHash(newNonce)) 666 if err == nil || !strings.Contains(err.Error(), "got wrong call data. wanted") { 667 t.Fatal("expected different error") 668 } 669 }) 670 671 t.Run("transaction reverted", func(t *testing.T) { 672 t.Parallel() 673 674 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, stakedAmount) 675 if err != nil { 676 t.Fatal(err) 677 } 678 679 contract := staking.New( 680 owner, 681 stakingContractAddress, 682 stakingContractABI, 683 bzzTokenAddress, 684 transactionMock.New( 685 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 686 if *request.To == stakingContractAddress { 687 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 688 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 689 } 690 return txHashOverlayChanged, nil 691 } 692 return txHashOverlayChanged, errors.New("sent to wrong contract") 693 }), 694 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 695 if txHash == txHashOverlayChanged { 696 return &types.Receipt{ 697 Status: 0, 698 }, nil 699 } 700 return nil, errors.New("unknown tx hash") 701 }), 702 ), 703 nonce, 704 false, 705 ) 706 707 _, err = contract.ChangeStakeOverlay(ctx, nonce) 708 if !errors.Is(err, transaction.ErrTransactionReverted) { 709 t.Fatalf("expected %v, got %v", transaction.ErrTransactionReverted, err) 710 } 711 }) 712 713 t.Run("transaction error", func(t *testing.T) { 714 t.Parallel() 715 716 expectedCallData, err := stakingContractABI.Pack("manageStake", nonce, stakedAmount) 717 if err != nil { 718 t.Fatal(err) 719 } 720 721 contract := staking.New( 722 owner, 723 stakingContractAddress, 724 stakingContractABI, 725 bzzTokenAddress, 726 transactionMock.New( 727 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 728 if *request.To == stakingContractAddress { 729 if !bytes.Equal(expectedCallData[:80], request.Data[:80]) { 730 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 731 } 732 return txHashOverlayChanged, nil 733 } 734 return common.Hash{}, errors.New("sent to wrong contract") 735 }), 736 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 737 if txHash == txHashOverlayChanged { 738 return nil, fmt.Errorf("unknown error") 739 } 740 return nil, errors.New("unknown tx hash") 741 }), 742 ), 743 nonce, 744 false, 745 ) 746 747 _, err = contract.ChangeStakeOverlay(ctx, nonce) 748 if err == nil || !strings.Contains(err.Error(), "unknown error") { 749 t.Fatal("expected different error") 750 } 751 }) 752 } 753 754 func TestGetCommittedStake(t *testing.T) { 755 t.Parallel() 756 757 ctx := context.Background() 758 owner := common.HexToAddress("abcd") 759 stakingAddress := common.HexToAddress("ffff") 760 bzzTokenAddress := common.HexToAddress("eeee") 761 nonce := common.BytesToHash(make([]byte, 32)) 762 763 expectedCallData, err := stakingContractABI.Pack("stakes", owner) 764 if err != nil { 765 t.Fatal(err) 766 } 767 768 t.Run("ok", func(t *testing.T) { 769 t.Parallel() 770 771 prevStake := big.NewInt(100000000000000000) 772 773 contract := staking.New( 774 owner, 775 stakingAddress, 776 stakingContractABI, 777 bzzTokenAddress, 778 transactionMock.New( 779 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 780 if *request.To == stakingAddress { 781 if !bytes.Equal(expectedCallData[:64], request.Data[:64]) { 782 return nil, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 783 } 784 return getPotentialStakeResponse(t, prevStake), nil 785 } 786 return nil, errors.New("unexpected call") 787 }), 788 ), 789 nonce, 790 false, 791 ) 792 793 stakedAmount, err := contract.GetPotentialStake(ctx) 794 if err != nil { 795 t.Fatal(err) 796 } 797 798 if stakedAmount.Cmp(prevStake) != 0 { 799 t.Fatalf("expected %v got %v", prevStake, stakedAmount) 800 } 801 }) 802 803 t.Run("error with unpacking", func(t *testing.T) { 804 t.Parallel() 805 expectedCallData, err := stakingContractABI.Pack("stakes", owner) 806 if err != nil { 807 t.Fatal(err) 808 } 809 810 contract := staking.New( 811 owner, 812 stakingAddress, 813 stakingContractABI, 814 bzzTokenAddress, 815 transactionMock.New( 816 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 817 if *request.To == stakingAddress { 818 if !bytes.Equal(expectedCallData[:64], request.Data[:64]) { 819 return nil, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 820 } 821 return []byte{}, nil 822 } 823 return nil, errors.New("unexpected call") 824 }), 825 ), 826 nonce, 827 false, 828 ) 829 830 _, err = contract.GetPotentialStake(ctx) 831 if err == nil { 832 t.Fatal("expected error with unpacking") 833 } 834 }) 835 836 t.Run("with invalid call data", func(t *testing.T) { 837 t.Parallel() 838 839 addr := swarm.MustParseHexAddress("f30c0aa7e9e2a0ef4c9b1b750ebfeaeb7c7c24da700bb089da19a46e3677824b") 840 841 prevStake := big.NewInt(0) 842 expectedCallData, err := stakingContractABI.Pack("stakes", common.BytesToHash(addr.Bytes())) 843 if err != nil { 844 t.Fatal(err) 845 } 846 847 contract := staking.New( 848 owner, 849 stakingAddress, 850 stakingContractABI, 851 bzzTokenAddress, 852 transactionMock.New( 853 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 854 if *request.To == stakingAddress { 855 if !bytes.Equal(expectedCallData[:64], request.Data[:64]) { 856 return nil, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 857 } 858 return prevStake.FillBytes(make([]byte, 32)), nil 859 } 860 return nil, errors.New("unexpected call") 861 }), 862 ), 863 nonce, 864 false, 865 ) 866 867 _, err = contract.GetPotentialStake(ctx) 868 if err == nil { 869 t.Fatal("expected error due to wrong call data") 870 } 871 }) 872 873 t.Run("transaction error", func(t *testing.T) { 874 t.Parallel() 875 876 contract := staking.New( 877 owner, 878 stakingAddress, 879 stakingContractABI, 880 bzzTokenAddress, 881 transactionMock.New( 882 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 883 return nil, errors.New("some error") 884 }), 885 ), 886 nonce, 887 false, 888 ) 889 890 _, err := contract.GetPotentialStake(ctx) 891 if err == nil { 892 t.Fatal("expected error") 893 } 894 }) 895 } 896 897 func TestGetWithdrawableStake(t *testing.T) { 898 t.Parallel() 899 900 ctx := context.Background() 901 owner := common.HexToAddress("abcd") 902 stakingAddress := common.HexToAddress("ffff") 903 bzzTokenAddress := common.HexToAddress("eeee") 904 nonce := common.BytesToHash(make([]byte, 32)) 905 906 expectedCallData, err := stakingContractABI.Pack("withdrawableStake") 907 if err != nil { 908 t.Fatal(err) 909 } 910 911 t.Run("ok", func(t *testing.T) { 912 t.Parallel() 913 914 prevStake := big.NewInt(100000000000000000) 915 916 contract := staking.New( 917 owner, 918 stakingAddress, 919 stakingContractABI, 920 bzzTokenAddress, 921 transactionMock.New( 922 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 923 if *request.To == stakingAddress { 924 if !bytes.Equal(expectedCallData[:32], request.Data[:32]) { 925 return nil, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 926 } 927 return prevStake.FillBytes(make([]byte, 32)), nil 928 } 929 return nil, errors.New("unexpected call") 930 }), 931 ), 932 nonce, 933 false, 934 ) 935 936 withdrawableStake, err := contract.GetWithdrawableStake(ctx) 937 if err != nil { 938 t.Fatal(err) 939 } 940 941 if withdrawableStake.Cmp(prevStake) != 0 { 942 t.Fatalf("expected %v got %v", prevStake, withdrawableStake) 943 } 944 }) 945 946 t.Run("error with unpacking", func(t *testing.T) { 947 t.Parallel() 948 expectedCallData, err := stakingContractABI.Pack("withdrawableStake") 949 if err != nil { 950 t.Fatal(err) 951 } 952 953 contract := staking.New( 954 owner, 955 stakingAddress, 956 stakingContractABI, 957 bzzTokenAddress, 958 transactionMock.New( 959 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 960 if *request.To == stakingAddress { 961 if !bytes.Equal(expectedCallData[:32], request.Data[:32]) { 962 return nil, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallData, request.Data) 963 } 964 return []byte{}, nil 965 } 966 return nil, errors.New("unexpected call") 967 }), 968 ), 969 nonce, 970 false, 971 ) 972 973 _, err = contract.GetPotentialStake(ctx) 974 if err == nil { 975 t.Fatal("expected error with unpacking") 976 } 977 }) 978 979 t.Run("transaction error", func(t *testing.T) { 980 t.Parallel() 981 982 contract := staking.New( 983 owner, 984 stakingAddress, 985 stakingContractABI, 986 bzzTokenAddress, 987 transactionMock.New( 988 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 989 return nil, errors.New("some error") 990 }), 991 ), 992 nonce, 993 false, 994 ) 995 996 _, err := contract.GetPotentialStake(ctx) 997 if err == nil { 998 t.Fatal("expected error") 999 } 1000 }) 1001 } 1002 1003 func TestWithdrawStake(t *testing.T) { 1004 t.Parallel() 1005 1006 ctx := context.Background() 1007 owner := common.HexToAddress("abcd") 1008 stakingContractAddress := common.HexToAddress("ffff") 1009 bzzTokenAddress := common.HexToAddress("eeee") 1010 nonce := common.BytesToHash(make([]byte, 32)) 1011 withdrawableStake := big.NewInt(100000000000000000) 1012 1013 t.Run("ok", func(t *testing.T) { 1014 t.Parallel() 1015 txHashWithdrawn := common.HexToHash("c3a1") 1016 1017 expectedCallDataForWithdraw, err := stakingContractABI.Pack("withdrawFromStake") 1018 if err != nil { 1019 t.Fatal(err) 1020 } 1021 expectedCallDataForGetStake, err := stakingContractABI.Pack("withdrawableStake") 1022 if err != nil { 1023 t.Fatal(err) 1024 } 1025 1026 contract := staking.New( 1027 owner, 1028 stakingContractAddress, 1029 stakingContractABI, 1030 bzzTokenAddress, 1031 transactionMock.New( 1032 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1033 if *request.To == stakingContractAddress { 1034 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1035 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1036 } 1037 return txHashWithdrawn, nil 1038 } 1039 return common.Hash{}, errors.New("sent to wrong contract") 1040 }), 1041 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1042 if txHash == txHashWithdrawn { 1043 return &types.Receipt{ 1044 Status: 1, 1045 }, nil 1046 } 1047 return nil, errors.New("unknown tx hash") 1048 }), 1049 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1050 if *request.To == stakingContractAddress { 1051 if bytes.Equal(expectedCallDataForGetStake[:32], request.Data[:32]) { 1052 return withdrawableStake.FillBytes(make([]byte, 32)), nil 1053 } 1054 } 1055 return nil, errors.New("unexpected call") 1056 }), 1057 ), 1058 nonce, 1059 false, 1060 ) 1061 1062 _, err = contract.WithdrawStake(ctx) 1063 if err != nil { 1064 t.Fatal(err) 1065 } 1066 }) 1067 1068 t.Run("has no stake", func(t *testing.T) { 1069 t.Parallel() 1070 1071 invalidStakedAmount := big.NewInt(0) 1072 1073 expectedCallDataForGetStake, err := stakingContractABI.Pack("withdrawableStake") 1074 if err != nil { 1075 t.Fatal(err) 1076 } 1077 1078 contract := staking.New( 1079 owner, 1080 stakingContractAddress, 1081 stakingContractABI, 1082 bzzTokenAddress, 1083 transactionMock.New( 1084 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1085 if *request.To == stakingContractAddress { 1086 if bytes.Equal(expectedCallDataForGetStake[:32], request.Data[:32]) { 1087 return invalidStakedAmount.FillBytes(make([]byte, 32)), nil 1088 } 1089 } 1090 return nil, errors.New("unexpected call") 1091 }), 1092 ), 1093 nonce, 1094 false, 1095 ) 1096 1097 _, err = contract.WithdrawStake(ctx) 1098 if !errors.Is(err, staking.ErrInsufficientStake) { 1099 t.Fatal(err) 1100 } 1101 }) 1102 1103 t.Run("send tx failed", func(t *testing.T) { 1104 t.Parallel() 1105 txHashWithdrawn := common.HexToHash("c3a1") 1106 1107 expectedCallDataForWithdraw, err := stakingContractABI.Pack("withdrawFromStake") 1108 if err != nil { 1109 t.Fatal(err) 1110 } 1111 expectedCallDataForGetStake, err := stakingContractABI.Pack("withdrawableStake") 1112 if err != nil { 1113 t.Fatal(err) 1114 } 1115 1116 expectedErr := errors.New("tx err") 1117 1118 contract := staking.New( 1119 owner, 1120 stakingContractAddress, 1121 stakingContractABI, 1122 bzzTokenAddress, 1123 transactionMock.New( 1124 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1125 if *request.To == stakingContractAddress { 1126 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1127 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1128 } 1129 return common.Hash{}, fmt.Errorf("send tx failed: %w", expectedErr) 1130 } 1131 return common.Hash{}, errors.New("sent to wrong contract") 1132 }), 1133 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1134 if txHash == txHashWithdrawn { 1135 return &types.Receipt{ 1136 Status: 1, 1137 }, nil 1138 } 1139 return nil, errors.New("unknown tx hash") 1140 }), 1141 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1142 if *request.To == stakingContractAddress { 1143 if bytes.Equal(expectedCallDataForGetStake[:32], request.Data[:32]) { 1144 return withdrawableStake.FillBytes(make([]byte, 32)), nil 1145 } 1146 } 1147 return nil, errors.New("unexpected call") 1148 }), 1149 ), 1150 nonce, 1151 false, 1152 ) 1153 1154 _, err = contract.WithdrawStake(ctx) 1155 if !errors.Is(err, expectedErr) { 1156 t.Fatalf("expected err %v, got %v", expectedErr, err) 1157 } 1158 }) 1159 1160 t.Run("tx reverted", func(t *testing.T) { 1161 t.Parallel() 1162 txHashWithdrawn := common.HexToHash("c3a1") 1163 1164 expectedCallDataForWithdraw, err := stakingContractABI.Pack("withdrawFromStake") 1165 if err != nil { 1166 t.Fatal(err) 1167 } 1168 expectedCallDataForGetStake, err := stakingContractABI.Pack("withdrawableStake") 1169 if err != nil { 1170 t.Fatal(err) 1171 } 1172 1173 contract := staking.New( 1174 owner, 1175 stakingContractAddress, 1176 stakingContractABI, 1177 bzzTokenAddress, 1178 transactionMock.New( 1179 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1180 if *request.To == stakingContractAddress { 1181 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1182 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1183 } 1184 return txHashWithdrawn, nil 1185 } 1186 return common.Hash{}, errors.New("sent to wrong contract") 1187 }), 1188 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1189 if txHash == txHashWithdrawn { 1190 return &types.Receipt{ 1191 Status: 0, 1192 }, nil 1193 } 1194 return nil, errors.New("unknown tx hash") 1195 }), 1196 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1197 if *request.To == stakingContractAddress { 1198 if bytes.Equal(expectedCallDataForGetStake[:32], request.Data[:32]) { 1199 return withdrawableStake.FillBytes(make([]byte, 32)), nil 1200 } 1201 } 1202 return nil, errors.New("unexpected call") 1203 }), 1204 ), 1205 nonce, 1206 false, 1207 ) 1208 1209 _, err = contract.WithdrawStake(ctx) 1210 if err == nil { 1211 t.Fatalf("expected non nil error, got nil") 1212 } 1213 }) 1214 1215 t.Run("get stake with err", func(t *testing.T) { 1216 t.Parallel() 1217 1218 expectedCallDataForGetStake, err := stakingContractABI.Pack("withdrawableStake") 1219 if err != nil { 1220 t.Fatal(err) 1221 } 1222 1223 contract := staking.New( 1224 owner, 1225 stakingContractAddress, 1226 stakingContractABI, 1227 bzzTokenAddress, 1228 transactionMock.New( 1229 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1230 if *request.To == stakingContractAddress { 1231 if bytes.Equal(expectedCallDataForGetStake[:32], request.Data[:32]) { 1232 return nil, fmt.Errorf("some error") 1233 } 1234 } 1235 return nil, errors.New("unexpected call") 1236 }), 1237 ), 1238 nonce, 1239 false, 1240 ) 1241 1242 _, err = contract.WithdrawStake(ctx) 1243 if err == nil { 1244 t.Fatalf("expected non nil error, got nil") 1245 } 1246 }) 1247 } 1248 1249 func TestMigrateStake(t *testing.T) { 1250 t.Parallel() 1251 1252 ctx := context.Background() 1253 owner := common.HexToAddress("abcd") 1254 stakingContractAddress := common.HexToAddress("ffff") 1255 bzzTokenAddress := common.HexToAddress("eeee") 1256 nonce := common.BytesToHash(make([]byte, 32)) 1257 stakedAmount := big.NewInt(100000000000000000) 1258 1259 t.Run("ok", func(t *testing.T) { 1260 1261 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1262 if err != nil { 1263 t.Fatal(err) 1264 } 1265 expectedCallDataForWithdraw, err := stakingContractABI.Pack("migrateStake") 1266 if err != nil { 1267 t.Fatal(err) 1268 } 1269 expectedCallDataForGetStake, err := stakingContractABI.Pack("nodeEffectiveStake", owner) 1270 if err != nil { 1271 t.Fatal(err) 1272 } 1273 1274 t.Parallel() 1275 txHashWithdrawn := common.HexToHash("c3a1") 1276 expected := big.NewInt(1) 1277 1278 contract := staking.New( 1279 owner, 1280 stakingContractAddress, 1281 stakingContractABI, 1282 bzzTokenAddress, 1283 transactionMock.New( 1284 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1285 if *request.To == stakingContractAddress { 1286 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1287 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1288 } 1289 return txHashWithdrawn, nil 1290 } 1291 return common.Hash{}, errors.New("sent to wrong contract") 1292 }), 1293 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1294 if txHash == txHashWithdrawn { 1295 return &types.Receipt{ 1296 Status: 1, 1297 }, nil 1298 } 1299 return nil, errors.New("unknown tx hash") 1300 }), 1301 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1302 if *request.To == stakingContractAddress { 1303 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1304 return expected.FillBytes(make([]byte, 32)), nil 1305 } 1306 if bytes.Equal(expectedCallDataForGetStake[:64], request.Data[:64]) { 1307 return stakedAmount.FillBytes(make([]byte, 32)), nil 1308 } 1309 } 1310 return nil, errors.New("unexpected call") 1311 }), 1312 ), 1313 nonce, 1314 false, 1315 ) 1316 1317 _, err = contract.MigrateStake(ctx) 1318 if err != nil { 1319 t.Fatal(err) 1320 } 1321 }) 1322 1323 t.Run("is paused", func(t *testing.T) { 1324 t.Parallel() 1325 expected := big.NewInt(0) 1326 1327 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1328 if err != nil { 1329 t.Fatal(err) 1330 } 1331 1332 contract := staking.New( 1333 owner, 1334 stakingContractAddress, 1335 stakingContractABI, 1336 bzzTokenAddress, 1337 transactionMock.New( 1338 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1339 if *request.To == stakingContractAddress { 1340 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1341 return expected.FillBytes(make([]byte, 32)), nil 1342 } 1343 } 1344 return nil, errors.New("unexpected call") 1345 }), 1346 ), 1347 nonce, 1348 false, 1349 ) 1350 1351 _, err = contract.MigrateStake(ctx) 1352 if !errors.Is(err, staking.ErrNotPaused) { 1353 t.Fatal(err) 1354 } 1355 }) 1356 1357 t.Run("invalid call data", func(t *testing.T) { 1358 t.Parallel() 1359 _, err := stakingContractABI.Pack("paused", owner) 1360 if err == nil { 1361 t.Fatalf("expected non nil error, got nil") 1362 } 1363 _, err = stakingContractABI.Pack("migrateStake", owner) 1364 if err == nil { 1365 t.Fatalf("expected non nil error, got nil") 1366 } 1367 1368 _, err = stakingContractABI.Pack("nodeEffectiveStake", stakedAmount) 1369 if err == nil { 1370 t.Fatalf("expected non nil error, got nil") 1371 } 1372 }) 1373 1374 t.Run("send tx failed", func(t *testing.T) { 1375 t.Parallel() 1376 txHashWithdrawn := common.HexToHash("c3a1") 1377 expected := big.NewInt(1) 1378 1379 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1380 if err != nil { 1381 t.Fatal(err) 1382 } 1383 expectedCallDataForWithdraw, err := stakingContractABI.Pack("migrateStake") 1384 if err != nil { 1385 t.Fatal(err) 1386 } 1387 expectedCallDataForGetStake, err := stakingContractABI.Pack("nodeEffectiveStake", owner) 1388 if err != nil { 1389 t.Fatal(err) 1390 } 1391 1392 contract := staking.New( 1393 owner, 1394 stakingContractAddress, 1395 stakingContractABI, 1396 bzzTokenAddress, 1397 transactionMock.New( 1398 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1399 if *request.To == stakingContractAddress { 1400 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1401 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1402 } 1403 return common.Hash{}, errors.New("send tx failed") 1404 } 1405 return common.Hash{}, errors.New("sent to wrong contract") 1406 }), 1407 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1408 if txHash == txHashWithdrawn { 1409 return &types.Receipt{ 1410 Status: 1, 1411 }, nil 1412 } 1413 return nil, errors.New("unknown tx hash") 1414 }), 1415 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1416 if *request.To == stakingContractAddress { 1417 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1418 return expected.FillBytes(make([]byte, 32)), nil 1419 } 1420 if bytes.Equal(expectedCallDataForGetStake[:64], request.Data[:64]) { 1421 return stakedAmount.FillBytes(make([]byte, 32)), nil 1422 } 1423 } 1424 return nil, errors.New("unexpected call") 1425 }), 1426 ), 1427 nonce, 1428 false, 1429 ) 1430 1431 _, err = contract.MigrateStake(ctx) 1432 if err == nil { 1433 t.Fatalf("expected non nil error, got nil") 1434 } 1435 }) 1436 1437 t.Run("tx reverted", func(t *testing.T) { 1438 1439 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1440 if err != nil { 1441 t.Fatal(err) 1442 } 1443 expectedCallDataForWithdraw, err := stakingContractABI.Pack("migrateStake") 1444 if err != nil { 1445 t.Fatal(err) 1446 } 1447 expectedCallDataForGetStake, err := stakingContractABI.Pack("nodeEffectiveStake", owner) 1448 if err != nil { 1449 t.Fatal(err) 1450 } 1451 1452 t.Parallel() 1453 txHashWithdrawn := common.HexToHash("c3a1") 1454 expected := big.NewInt(1) 1455 1456 contract := staking.New( 1457 owner, 1458 stakingContractAddress, 1459 stakingContractABI, 1460 bzzTokenAddress, 1461 transactionMock.New( 1462 transactionMock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest, boost int) (txHash common.Hash, err error) { 1463 if *request.To == stakingContractAddress { 1464 if !bytes.Equal(expectedCallDataForWithdraw[:], request.Data[:]) { 1465 return common.Hash{}, fmt.Errorf("got wrong call data. wanted %x, got %x", expectedCallDataForWithdraw, request.Data) 1466 } 1467 return txHashWithdrawn, nil 1468 } 1469 return common.Hash{}, errors.New("sent to wrong contract") 1470 }), 1471 transactionMock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { 1472 if txHash == txHashWithdrawn { 1473 return &types.Receipt{ 1474 Status: 0, 1475 }, nil 1476 } 1477 return nil, errors.New("unknown tx hash") 1478 }), 1479 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1480 if *request.To == stakingContractAddress { 1481 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1482 return expected.FillBytes(make([]byte, 32)), nil 1483 } 1484 if bytes.Equal(expectedCallDataForGetStake[:64], request.Data[:64]) { 1485 return stakedAmount.FillBytes(make([]byte, 32)), nil 1486 } 1487 } 1488 return nil, errors.New("unexpected call") 1489 }), 1490 ), 1491 nonce, 1492 false, 1493 ) 1494 1495 _, err = contract.MigrateStake(ctx) 1496 if err == nil { 1497 t.Fatalf("expected non nil error, got nil") 1498 } 1499 }) 1500 1501 t.Run("is paused with err", func(t *testing.T) { 1502 1503 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1504 if err != nil { 1505 t.Fatal(err) 1506 } 1507 1508 t.Parallel() 1509 1510 contract := staking.New( 1511 owner, 1512 stakingContractAddress, 1513 stakingContractABI, 1514 bzzTokenAddress, 1515 transactionMock.New( 1516 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1517 if *request.To == stakingContractAddress { 1518 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1519 return nil, fmt.Errorf("some error") 1520 } 1521 } 1522 return nil, errors.New("unexpected call") 1523 }), 1524 ), 1525 nonce, 1526 false, 1527 ) 1528 1529 _, err = contract.WithdrawStake(ctx) 1530 if err == nil { 1531 t.Fatalf("expected non nil error, got nil") 1532 } 1533 }) 1534 1535 t.Run("get stake with err", func(t *testing.T) { 1536 1537 expectedCallDataForPaused, err := stakingContractABI.Pack("paused") 1538 if err != nil { 1539 t.Fatal(err) 1540 } 1541 expectedCallDataForGetStake, err := stakingContractABI.Pack("nodeEffectiveStake", owner) 1542 if err != nil { 1543 t.Fatal(err) 1544 } 1545 1546 t.Parallel() 1547 expected := big.NewInt(1) 1548 1549 contract := staking.New( 1550 owner, 1551 stakingContractAddress, 1552 stakingContractABI, 1553 bzzTokenAddress, 1554 transactionMock.New( 1555 transactionMock.WithCallFunc(func(ctx context.Context, request *transaction.TxRequest) (result []byte, err error) { 1556 if *request.To == stakingContractAddress { 1557 if bytes.Equal(expectedCallDataForPaused[:], request.Data[:]) { 1558 return expected.FillBytes(make([]byte, 32)), nil 1559 } 1560 if bytes.Equal(expectedCallDataForGetStake[:64], request.Data[:64]) { 1561 return nil, fmt.Errorf("some error") 1562 } 1563 } 1564 return nil, errors.New("unexpected call") 1565 }), 1566 ), 1567 nonce, 1568 false, 1569 ) 1570 1571 _, err = contract.MigrateStake(ctx) 1572 if err == nil { 1573 t.Fatalf("expected non nil error, got nil") 1574 } 1575 }) 1576 } 1577 1578 func getPotentialStakeResponse(t *testing.T, amount *big.Int) []byte { 1579 t.Helper() 1580 1581 ret := make([]byte, 32+32+32+32+32+32) 1582 copy(ret, swarm.RandAddress(t).Bytes()) 1583 copy(ret[64:], amount.FillBytes(make([]byte, 32))) 1584 1585 return ret 1586 }