diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000000..381e9d9fc4 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,20 @@ +reviews: + path_filters: + - "**/*.pb.go" + - "**/*.pb.gw.go" + path_instructions: + - path: '**/*.go' + instructions: >- + Review the Go code, point out issues relative to principles of clean + code, expressiveness, and performance. + - path: '**/*.proto' + instructions: >- + Review the Protobuf definitions, point out issues relative to + compatibility, and expressiveness. + - path: '**/*.sh' + instructions: >- + Review the shell scripts, point out issues relative to security, + performance, and maintainability. + auto_review: + base_branches: + - develop \ No newline at end of file diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index a396f4d71d..e96bb39e46 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -113,11 +113,10 @@ jobs: - name: Run golangci-lint if: ${{ github.event.inputs.skip_checks != 'true' }} - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: v1.54 + version: v1.59 skip-cache: true - args: --out-format=json - name: Mark Job Complete Skipped if: ${{ github.event.inputs.skip_checks == 'true' }} diff --git a/.github/workflows/sast-linters.yml b/.github/workflows/sast-linters.yml index 3b8381e19d..2372ff5264 100644 --- a/.github/workflows/sast-linters.yml +++ b/.github/workflows/sast-linters.yml @@ -69,11 +69,10 @@ jobs: go-version: '1.20' - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: v1.54 + version: v1.59 skip-cache: true - args: --out-format=json nosec_alert: runs-on: ubuntu-22.04 diff --git a/.golangci.yml b/.golangci.yml index f393d5880f..c9567f4b3b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,8 @@ +run: + go: '1.20' # as in go.mod + timeout: 5m + tests: false # exclude test from linting + linters: disable-all: true enable: @@ -18,24 +23,32 @@ linters: - bodyclose - unconvert - unused + - gci + - gofmt + - whitespace + linters-settings: gocyclo: min-complexity: 11 errcheck: - ignore: fmt:.*,io/ioutil:^Read.*,github.com/spf13/cobra:MarkFlagRequired,github.com/spf13/viper:BindPFlag - golint: - min-confidence: 1.1 + exclude-functions: + - fmt:.* + - io/ioutil:^Read.*, + - github.com/spf13/cobra:MarkFlagRequired + - github.com/spf13/viper:BindPFlag exhaustive: check-generated: false - exhaustivestruct: - check-generated: false + gci: + # Gci controls Go package import order and makes it always deterministic + # https://golangci-lint.run/usage/linters/#gci + sections: + - standard + - default + - prefix(github.com/zeta-chain/zetacore) + skip-generated: true + issues: + exclude-generated: strict exclude: - composite -run: - tests: false - deadline: 15m - timeout: 5m - skip-files: - - ".*\\.pb\\.go$" - + exclude-dirs: [ ".git", ".github" ] \ No newline at end of file diff --git a/Makefile b/Makefile index 0520f1f319..360e071485 100644 --- a/Makefile +++ b/Makefile @@ -145,14 +145,8 @@ gosec: ### Formatting ### ############################################################################### -fmt-import: - @bash ./scripts/fmt-imports.sh -@PHONY: fmt-import - -fmt-golines: - @echo "--> Formatting Go lines" - @bash ./scripts/fmt-golines.sh -.PHONY: fmt-golines +fmt: + @bash ./scripts/fmt.sh ############################################################################### ### Generation commands ### @@ -199,7 +193,7 @@ mocks: .PHONY: mocks # generate also includes Go code formatting -generate: proto-gen openapi specs typescript docs-zetacored mocks fmt-import fmt-golines +generate: proto-gen openapi specs typescript docs-zetacored mocks fmt .PHONY: generate ############################################################################### diff --git a/app/app.go b/app/app.go index 0688ca75db..f5d0abd7e9 100644 --- a/app/app.go +++ b/app/app.go @@ -316,7 +316,6 @@ func New( appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *App { - appCodec := encodingConfig.Codec cdc := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry diff --git a/app/export.go b/app/export.go index d75de64514..1f1ae26a96 100644 --- a/app/export.go +++ b/app/export.go @@ -17,7 +17,6 @@ import ( func (app *App) ExportAppStateAndValidators( forZeroHeight bool, jailAllowedAddrs []string, modulesToExport []string, ) (servertypes.ExportedApp, error) { - // as if they could withdraw from the start of the next block ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) diff --git a/changelog.md b/changelog.md index 176355afc1..f7a819e383 100644 --- a/changelog.md +++ b/changelog.md @@ -50,6 +50,8 @@ * [2317](https://github.com/zeta-chain/node/pull/2317) - add ValidateOutbound method for cctx orchestrator * [2340](https://github.com/zeta-chain/node/pull/2340) - add ValidateInbound method for cctx orchestrator * [2344](https://github.com/zeta-chain/node/pull/2344) - group common data of EVM/Bitcoin signer and observer using base structs +* [2357](https://github.com/zeta-chain/node/pull/2357) - integrate base Signer structure into EVM/Bitcoin Signer +* [2375](https://github.com/zeta-chain/node/pull/2375) - improve & speedup code formatting ### Tests @@ -65,6 +67,9 @@ * [2299](https://github.com/zeta-chain/node/pull/2299) - add `zetae2e` command to deploy test contracts * [2360](https://github.com/zeta-chain/node/pull/2360) - add stateful e2e tests. * [2349](https://github.com/zeta-chain/node/pull/2349) - add TestBitcoinDepositRefund and WithdrawBitcoinMultipleTimes E2E tests +* [2368](https://github.com/zeta-chain/node/pull/2368) - eliminate panic usage across testing suite +* [2369](https://github.com/zeta-chain/node/pull/2369) - fix random cross-chain swap failure caused by using tiny UTXO + ### Fixes @@ -75,6 +80,7 @@ * [2243](https://github.com/zeta-chain/node/pull/2243) - fix incorrect bitcoin outbound height in the CCTX outbound parameter * [2256](https://github.com/zeta-chain/node/pull/2256) - fix rate limiter falsely included reverted non-withdraw cctxs * [2327](https://github.com/zeta-chain/node/pull/2327) - partially cherry picked the fix to Bitcoin outbound dust amount +* [2362](https://github.com/zeta-chain/node/pull/2362) - set 1000 satoshis as minimum BTC amount that can be withdrawn from zEVM ### CI diff --git a/cmd/zetaclientd/debug.go b/cmd/zetaclientd/debug.go index 881997d0ec..4ba2f01516 100644 --- a/cmd/zetaclientd/debug.go +++ b/cmd/zetaclientd/debug.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "io" "strconv" "strings" "sync" @@ -13,7 +12,6 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/onrik/ethrpc" - "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/zeta-chain/zetacore/pkg/chains" @@ -61,7 +59,6 @@ func DebugCmd() *cobra.Command { } inboundHash := args[0] var ballotIdentifier string - chainLogger := zerolog.New(io.Discard).Level(zerolog.Disabled) // create a new zetacore client client, err := zetacore.NewClient( @@ -93,7 +90,6 @@ func DebugCmd() *cobra.Command { Mu: &sync.Mutex{}, } evmObserver.WithZetacoreClient(client) - evmObserver.WithLogger(chainLogger) var ethRPC *ethrpc.EthRPC var client *ethclient.Client coinType := coin.CoinType_Cmd @@ -172,7 +168,6 @@ func DebugCmd() *cobra.Command { Mu: &sync.Mutex{}, } btcObserver.WithZetacoreClient(client) - btcObserver.WithLogger(chainLogger) btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) connCfg := &rpcclient.ConnConfig{ Host: cfg.BitcoinConfig.RPCHost, @@ -192,7 +187,6 @@ func DebugCmd() *cobra.Command { if err != nil { return err } - } fmt.Println("BallotIdentifier : ", ballotIdentifier) diff --git a/cmd/zetaclientd/gen_pre_params.go b/cmd/zetaclientd/gen_pre_params.go index c797a9f206..7837867b74 100644 --- a/cmd/zetaclientd/gen_pre_params.go +++ b/cmd/zetaclientd/gen_pre_params.go @@ -18,7 +18,7 @@ var GenPrePramsCmd = &cobra.Command{ Use: "gen-pre-params ", Short: "Generate pre parameters for TSS", Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { startTime := time.Now() preParams, err := keygen.GeneratePreParams(time.Second * 300) if err != nil { diff --git a/cmd/zetaclientd/keygen_tss.go b/cmd/zetaclientd/keygen_tss.go index 0e74d878ca..007ce9ec8c 100644 --- a/cmd/zetaclientd/keygen_tss.go +++ b/cmd/zetaclientd/keygen_tss.go @@ -203,7 +203,6 @@ func SetTSSPubKey(tss *mc.TSS, logger zerolog.Logger) error { } logger.Info().Msgf("TSS address in hex: %s", tss.EVMAddress().Hex()) return nil - } func TestTSS(tss *mc.TSS, logger zerolog.Logger) error { keygenLogger := logger.With().Str("module", "test-keygen").Logger() diff --git a/cmd/zetaclientd/main.go b/cmd/zetaclientd/main.go index 99aaf55c10..b0b8ffb0e1 100644 --- a/cmd/zetaclientd/main.go +++ b/cmd/zetaclientd/main.go @@ -42,5 +42,4 @@ func SetupConfigForTest() { }) rand.Seed(time.Now().UnixNano()) - } diff --git a/cmd/zetaclientd/p2p_diagnostics.go b/cmd/zetaclientd/p2p_diagnostics.go index 9816c16eab..330f520013 100644 --- a/cmd/zetaclientd/p2p_diagnostics.go +++ b/cmd/zetaclientd/p2p_diagnostics.go @@ -32,7 +32,6 @@ func RunDiagnostics( hotkeyPk cryptotypes.PrivKey, cfg config.Config, ) error { - startLogger.Warn().Msg("P2P Diagnostic mode enabled") startLogger.Warn().Msgf("seed peer: %s", peers) priKey := secp256k1.PrivKey(hotkeyPk.Bytes()[:32]) @@ -46,7 +45,6 @@ func RunDiagnostics( var s *metrics.TelemetryServer if len(peers) == 0 { startLogger.Warn().Msg("No seed peer specified; assuming I'm the host") - } p2pPriKey, err := crypto.UnmarshalSecp256k1PrivateKey(priKey[:]) if err != nil { diff --git a/cmd/zetaclientd/utils.go b/cmd/zetaclientd/utils.go index 521c6dc858..43caf04c11 100644 --- a/cmd/zetaclientd/utils.go +++ b/cmd/zetaclientd/utils.go @@ -54,13 +54,14 @@ func CreateZetacoreClient( return client, nil } +// CreateSignerMap creates a map of ChainSigners for all chains in the config func CreateSignerMap( appContext *context.AppContext, tss interfaces.TSSSigner, logger base.Logger, ts *metrics.TelemetryServer, ) (map[int64]interfaces.ChainSigner, error) { - coreContext := appContext.ZetacoreContext() + zetacoreContext := appContext.ZetacoreContext() signerMap := make(map[int64]interfaces.ChainSigner) // EVM signers @@ -68,7 +69,7 @@ func CreateSignerMap( if evmConfig.Chain.IsZetaChain() { continue } - evmChainParams, found := coreContext.GetEVMChainParams(evmConfig.Chain.ChainId) + evmChainParams, found := zetacoreContext.GetEVMChainParams(evmConfig.Chain.ChainId) if !found { logger.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) continue @@ -77,15 +78,15 @@ func CreateSignerMap( erc20CustodyAddress := ethcommon.HexToAddress(evmChainParams.Erc20CustodyContractAddress) signer, err := evmsigner.NewSigner( evmConfig.Chain, - evmConfig.Endpoint, + zetacoreContext, tss, + ts, + logger, + evmConfig.Endpoint, config.GetConnectorABI(), config.GetERC20CustodyABI(), mpiAddress, - erc20CustodyAddress, - coreContext, - logger, - ts) + erc20CustodyAddress) if err != nil { logger.Std.Error().Err(err).Msgf("NewEVMSigner error for chain %s", evmConfig.Chain.String()) continue @@ -95,7 +96,7 @@ func CreateSignerMap( // BTC signer btcChain, btcConfig, enabled := appContext.GetBTCChainAndConfig() if enabled { - signer, err := btcsigner.NewSigner(btcConfig, tss, logger, ts, coreContext) + signer, err := btcsigner.NewSigner(btcChain, zetacoreContext, tss, ts, logger, btcConfig) if err != nil { logger.Std.Error().Err(err).Msgf("NewBTCSigner error for chain %s", btcChain.String()) } else { @@ -139,7 +140,6 @@ func CreateChainObserverMap( co, err := btcobserver.NewObserver(appContext, btcChain, zetacoreClient, tss, dbpath, logger, btcConfig, ts) if err != nil { logger.Std.Error().Err(err).Msgf("NewObserver error for bitcoin chain %s", btcChain.String()) - } else { observerMap[btcChain.ChainId] = co } diff --git a/cmd/zetacored/add_observer_list.go b/cmd/zetacored/add_observer_list.go index fd614efbef..e2dd16a5b5 100644 --- a/cmd/zetacored/add_observer_list.go +++ b/cmd/zetacored/add_observer_list.go @@ -104,7 +104,6 @@ func AddObserverListCmd() *cobra.Command { ObserverBalance := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, observerTokens)) // Generate the grant authorizations and created observer list for chain for _, info := range observerInfo { - if isValidatorOnly(info.IsObserver) { balances = append(balances, banktypes.Balance{ Address: info.ObserverAddress, @@ -403,7 +402,6 @@ func addStakingGrants(grants []authz.GrantAuthorization, info ObserverInfoReader }) return grants - } func AddGenesisAccount( diff --git a/cmd/zetacored/main.go b/cmd/zetacored/main.go index b00e3dd337..69fa673548 100644 --- a/cmd/zetacored/main.go +++ b/cmd/zetacored/main.go @@ -18,7 +18,6 @@ func main() { rootCmd, _ := NewRootCmd() if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { - switch e := err.(type) { case server.ErrorCode: os.Exit(e.Code) diff --git a/cmd/zetacored/parse_genesis.go b/cmd/zetacored/parse_genesis.go index ec0a9bd313..8f177ee7ef 100644 --- a/cmd/zetacored/parse_genesis.go +++ b/cmd/zetacored/parse_genesis.go @@ -129,7 +129,6 @@ func ImportDataIntoFile( cdc codec.Codec, modifyEnabled bool, ) error { - appState, err := genutiltypes.GenesisStateFromGenDoc(*genDoc) if err != nil { return err diff --git a/cmd/zetae2e/local/admin.go b/cmd/zetae2e/local/admin.go index 1ac4cb6b60..63cff6fe23 100644 --- a/cmd/zetae2e/local/admin.go +++ b/cmd/zetae2e/local/admin.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -20,17 +19,6 @@ func adminTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("admin panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for erc20 advanced test adminRunner, err := initTestRunner( "admin", diff --git a/cmd/zetae2e/local/bitcoin.go b/cmd/zetae2e/local/bitcoin.go index d0f4d8bb12..cfb0501a8c 100644 --- a/cmd/zetae2e/local/bitcoin.go +++ b/cmd/zetae2e/local/bitcoin.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -22,18 +21,6 @@ func bitcoinTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("bitcoin panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for bitcoin test bitcoinRunner, err := initTestRunner( "bitcoin", diff --git a/cmd/zetae2e/local/erc20.go b/cmd/zetae2e/local/erc20.go index b7fd74f0d8..fe0fa8bb8a 100644 --- a/cmd/zetae2e/local/erc20.go +++ b/cmd/zetae2e/local/erc20.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -20,18 +19,6 @@ func erc20TestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("erc20 panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for erc20 test erc20Runner, err := initTestRunner( "erc20", diff --git a/cmd/zetae2e/local/ethereum.go b/cmd/zetae2e/local/ethereum.go index efb37f1fa1..fa9e7754e2 100644 --- a/cmd/zetae2e/local/ethereum.go +++ b/cmd/zetae2e/local/ethereum.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -21,18 +20,6 @@ func ethereumTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("ethereum panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for ether test ethereumRunner, err := initTestRunner( "ether", diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index 364bdf80a4..bd9dd654a2 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -2,7 +2,6 @@ package local import ( "context" - "fmt" "os" "path/filepath" "time" @@ -18,6 +17,7 @@ import ( "github.com/zeta-chain/zetacore/e2e/txserver" "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/testutil" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -42,6 +42,8 @@ var ( TestTimeout = 15 * time.Minute ) +var noError = testutil.NoError + // NewLocalCmd returns the local command // which runs the E2E tests locally on the machine with localnet for each blockchain func NewLocalCmd() *cobra.Command { @@ -70,58 +72,21 @@ func NewLocalCmd() *cobra.Command { func localE2ETest(cmd *cobra.Command, _ []string) { // fetch flags - waitForHeight, err := cmd.Flags().GetInt64(flagWaitForHeight) - if err != nil { - panic(err) - } - contractsDeployed, err := cmd.Flags().GetBool(flagContractsDeployed) - if err != nil { - panic(err) - } - verbose, err := cmd.Flags().GetBool(flagVerbose) - if err != nil { - panic(err) - } - configOut, err := cmd.Flags().GetString(flagConfigOut) - if err != nil { - panic(err) - } - testAdmin, err := cmd.Flags().GetBool(flagTestAdmin) - if err != nil { - panic(err) - } - testPerformance, err := cmd.Flags().GetBool(flagTestPerformance) - if err != nil { - panic(err) - } - testCustom, err := cmd.Flags().GetBool(flagTestCustom) - if err != nil { - panic(err) - } - skipRegular, err := cmd.Flags().GetBool(flagSkipRegular) - if err != nil { - panic(err) - } - light, err := cmd.Flags().GetBool(flagLight) - if err != nil { - panic(err) - } - setupOnly, err := cmd.Flags().GetBool(flagSetupOnly) - if err != nil { - panic(err) - } - skipSetup, err := cmd.Flags().GetBool(flagSkipSetup) - if err != nil { - panic(err) - } - skipBitcoinSetup, err := cmd.Flags().GetBool(flagSkipBitcoinSetup) - if err != nil { - panic(err) - } - skipHeaderProof, err := cmd.Flags().GetBool(flagSkipHeaderProof) - if err != nil { - panic(err) - } + var ( + waitForHeight = must(cmd.Flags().GetInt64(flagWaitForHeight)) + contractsDeployed = must(cmd.Flags().GetBool(flagContractsDeployed)) + verbose = must(cmd.Flags().GetBool(flagVerbose)) + configOut = must(cmd.Flags().GetString(flagConfigOut)) + testAdmin = must(cmd.Flags().GetBool(flagTestAdmin)) + testPerformance = must(cmd.Flags().GetBool(flagTestPerformance)) + testCustom = must(cmd.Flags().GetBool(flagTestCustom)) + skipRegular = must(cmd.Flags().GetBool(flagSkipRegular)) + light = must(cmd.Flags().GetBool(flagLight)) + setupOnly = must(cmd.Flags().GetBool(flagSetupOnly)) + skipSetup = must(cmd.Flags().GetBool(flagSkipSetup)) + skipBitcoinSetup = must(cmd.Flags().GetBool(flagSkipBitcoinSetup)) + skipHeaderProof = must(cmd.Flags().GetBool(flagSkipHeaderProof)) + ) logger := runner.NewLogger(verbose, color.FgWhite, "setup") @@ -146,16 +111,14 @@ func localE2ETest(cmd *cobra.Command, _ []string) { // initialize tests config conf, err := GetConfig(cmd) - if err != nil { - panic(err) - } + noError(err) // initialize context ctx, cancel := context.WithCancel(context.Background()) // wait for a specific height on ZetaChain if waitForHeight != 0 { - utils.WaitForBlockHeight(ctx, waitForHeight, conf.RPCs.ZetaCoreRPC, logger) + noError(utils.WaitForBlockHeight(ctx, waitForHeight, conf.RPCs.ZetaCoreRPC, logger)) } // set account prefix to zeta @@ -167,9 +130,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { []string{UserFungibleAdminPrivateKey}, conf.ZetaChainID, ) - if err != nil { - panic(fmt.Errorf("failed to initialize ZetaChain tx server: %w", err)) - } + noError(err) // initialize deployer runner with config deployerRunner, err := zetae2econfig.RunnerFromConfig( @@ -182,9 +143,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) { logger, runner.WithZetaTxServer(zetaTxServer), ) - if err != nil { - panic(err) - } + noError(err) // wait for keygen to be completed // if setup is skipped, we assume that the keygen is already completed @@ -193,16 +152,13 @@ func localE2ETest(cmd *cobra.Command, _ []string) { } // query and set the TSS - if err := deployerRunner.SetTSSAddresses(); err != nil { - panic(err) - } + noError(deployerRunner.SetTSSAddresses()) if !skipHeaderProof { - if err := deployerRunner.EnableHeaderVerification([]int64{ + noError(deployerRunner.EnableHeaderVerification([]int64{ chains.GoerliLocalnet.ChainId, - chains.BitcoinRegtest.ChainId}); err != nil { - panic(err) - } + chains.BitcoinRegtest.ChainId, + })) } // setting up the networks @@ -212,30 +168,22 @@ func localE2ETest(cmd *cobra.Command, _ []string) { deployerRunner.SetupEVM(contractsDeployed, true) deployerRunner.SetZEVMContracts() - - // NOTE: this method return an error so we handle it and panic if it occurs unlike other method that panics directly - // TODO: all methods should return errors instead of panicking and this current function should also return an error - // https://github.com/zeta-chain/node/issues/1500 - if err := deployerRunner.FundEmissionsPool(); err != nil { - panic(err) - } + noError(deployerRunner.FundEmissionsPool()) deployerRunner.MintERC20OnEvm(10000) logger.Print("✅ setup completed in %s", time.Since(startTime)) } + // if a config output is specified, write the config if configOut != "" { newConfig := zetae2econfig.ExportContractsFromRunner(deployerRunner, conf) - configOut, err := filepath.Abs(configOut) - if err != nil { - panic(err) - } // write config into stdout - if err := config.WriteConfig(configOut, newConfig); err != nil { - panic(err) - } + configOut, err := filepath.Abs(configOut) + noError(err) + + noError(config.WriteConfig(configOut, newConfig)) logger.Print("✅ config file written in %s", configOut) } @@ -407,3 +355,7 @@ func waitKeygenHeight( logger.Info("Last ZetaHeight: %d", response.Height) } } + +func must[T any](v T, err error) T { + return testutil.Must(v, err) +} diff --git a/cmd/zetae2e/local/misc.go b/cmd/zetae2e/local/misc.go index 081905b5ee..65467ec9e5 100644 --- a/cmd/zetae2e/local/misc.go +++ b/cmd/zetae2e/local/misc.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -20,18 +19,6 @@ func miscTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("misc panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for misc test miscRunner, err := initTestRunner( "misc", diff --git a/cmd/zetae2e/local/performance.go b/cmd/zetae2e/local/performance.go index 4b83d66307..7d289c4e90 100644 --- a/cmd/zetae2e/local/performance.go +++ b/cmd/zetae2e/local/performance.go @@ -5,7 +5,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -23,18 +22,6 @@ func ethereumDepositPerformanceRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("ethereum deposit perf panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for ether test r, err := initTestRunner( "ether", @@ -77,18 +64,6 @@ func ethereumWithdrawPerformanceRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("ethereum withdraw perf panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for ether test r, err := initTestRunner( "ether", diff --git a/cmd/zetae2e/local/zeta.go b/cmd/zetae2e/local/zeta.go index 1f95c5f6d6..6f5039b63f 100644 --- a/cmd/zetae2e/local/zeta.go +++ b/cmd/zetae2e/local/zeta.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -20,18 +19,6 @@ func zetaTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("zeta panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for zeta test zetaRunner, err := initTestRunner( "zeta", diff --git a/cmd/zetae2e/local/zevm_mp.go b/cmd/zetae2e/local/zevm_mp.go index 969dcfda64..f95fa24390 100644 --- a/cmd/zetae2e/local/zevm_mp.go +++ b/cmd/zetae2e/local/zevm_mp.go @@ -2,7 +2,6 @@ package local import ( "fmt" - "runtime" "time" "github.com/fatih/color" @@ -20,18 +19,6 @@ func zevmMPTestRoutine( testNames ...string, ) func() error { return func() (err error) { - // return an error on panic - // TODO: remove and instead return errors in the tests - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("zevm mp panic: %v, stack trace %s", r, stack[:n]) - } - }() - // initialize runner for zevm mp test zevmMPRunner, err := initTestRunner( "zevm_mp", diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index 5ed6babf6b..7d57500823 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -3,6 +3,8 @@ package main import ( "context" "errors" + "fmt" + "os" "strings" "time" @@ -35,17 +37,13 @@ For example: zetae2e run deposit:1000 withdraw: --config config.yml`, } cmd.Flags().StringVarP(&configFile, flagConfig, "c", "", "path to the configuration file") - err := cmd.MarkFlagRequired(flagConfig) - if err != nil { - panic(err) + if err := cmd.MarkFlagRequired(flagConfig); err != nil { + fmt.Println("Error marking flag as required") + os.Exit(1) } // Retain the verbose flag - cmd.Flags().Bool( - flagVerbose, - false, - "set to true to enable verbose logging", - ) + cmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging") return cmd } @@ -75,11 +73,11 @@ func runE2ETest(cmd *cobra.Command, args []string) error { // initialize context ctx, cancel := context.WithCancel(context.Background()) + defer cancel() // get EVM address from config evmAddr := conf.Accounts.EVMAddress if !ethcommon.IsHexAddress(evmAddr) { - cancel() return errors.New("invalid EVM address") } @@ -94,7 +92,6 @@ func runE2ETest(cmd *cobra.Command, args []string) error { logger, ) if err != nil { - cancel() return err } @@ -112,31 +109,26 @@ func runE2ETest(cmd *cobra.Command, args []string) error { balancesBefore, err := testRunner.GetAccountBalances(true) if err != nil { - cancel() return err } // parse test names and arguments from cmd args and run them userTestsConfigs, err := parseCmdArgsToE2ETestRunConfig(args) if err != nil { - cancel() return err } testsToRun, err := testRunner.GetE2ETestsToRunByConfig(e2etests.AllE2ETests, userTestsConfigs) if err != nil { - cancel() return err } reports, err := testRunner.RunE2ETestsIntoReport(testsToRun) if err != nil { - cancel() return err } balancesAfter, err := testRunner.GetAccountBalances(true) if err != nil { - cancel() return err } diff --git a/cmd/zetae2e/stress.go b/cmd/zetae2e/stress.go index 472b01fc50..ca0446cbc9 100644 --- a/cmd/zetae2e/stress.go +++ b/cmd/zetae2e/stress.go @@ -24,6 +24,7 @@ import ( "github.com/zeta-chain/zetacore/cmd/zetae2e/local" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" + "github.com/zeta-chain/zetacore/testutil" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -47,6 +48,8 @@ type stressArguments struct { var stressTestArgs = stressArguments{} +var noError = testutil.NoError + func NewStressTestCmd() *cobra.Command { var StressCmd = &cobra.Command{ Use: "stress", @@ -88,27 +91,15 @@ func StressTest(cmd *cobra.Command, _ []string) { cosmosConf.Seal() // initialize E2E tests config - conf, err := local.GetConfig(cmd) - if err != nil { - panic(err) - } + conf := must(local.GetConfig(cmd)) // Initialize clients ---------------------------------------------------------------- - evmClient, err := ethclient.Dial(conf.RPCs.EVM) - if err != nil { - panic(err) - } + evmClient := must(ethclient.Dial(conf.RPCs.EVM)) + bal := must(evmClient.BalanceAt(context.TODO(), local.DeployerAddress, nil)) - bal, err := evmClient.BalanceAt(context.TODO(), local.DeployerAddress, nil) - if err != nil { - panic(err) - } fmt.Printf("Deployer address: %s, balance: %d Wei\n", local.DeployerAddress.Hex(), bal) - grpcConn, err := grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure()) - if err != nil { - panic(err) - } + grpcConn := must(grpc.Dial(conf.RPCs.ZetaCoreGRPC, grpc.WithInsecure())) cctxClient := crosschaintypes.NewQueryClient(grpcConn) // ----------------------------------------------------------------------------------- @@ -136,14 +127,11 @@ func StressTest(cmd *cobra.Command, _ []string) { // initialize context ctx, cancel := context.WithCancel(context.Background()) - verbose, err := cmd.Flags().GetBool(flagVerbose) - if err != nil { - panic(err) - } + verbose := must(cmd.Flags().GetBool(flagVerbose)) logger := runner.NewLogger(verbose, color.FgWhite, "setup") // initialize E2E test runner - e2eTest, err := zetae2econfig.RunnerFromConfig( + e2eTest := must(zetae2econfig.RunnerFromConfig( ctx, "deployer", cancel, @@ -151,69 +139,47 @@ func StressTest(cmd *cobra.Command, _ []string) { local.DeployerAddress, local.DeployerPrivateKey, logger, - ) - if err != nil { - panic(err) - } + )) // setup TSS addresses - if err := e2eTest.SetTSSAddresses(); err != nil { - panic(err) - } - + noError(e2eTest.SetTSSAddresses()) e2eTest.SetupEVM(stressTestArgs.contractsDeployed, true) // If stress test is running on local docker environment - if stressTestArgs.network == "LOCAL" { + switch stressTestArgs.network { + case "LOCAL": // deploy and set zevm contract e2eTest.SetZEVMContracts() // deposit on ZetaChain e2eTest.DepositEther(false) e2eTest.DepositZeta() - } else if stressTestArgs.network == "TESTNET" { - ethZRC20Addr, err := e2eTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) - if err != nil { - panic(err) - } + case "TESTNET": + ethZRC20Addr := must(e2eTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5))) e2eTest.ETHZRC20Addr = ethZRC20Addr - e2eTest.ETHZRC20, err = zrc20.NewZRC20(e2eTest.ETHZRC20Addr, e2eTest.ZEVMClient) - if err != nil { - panic(err) - } - } else { - err := errors.New("invalid network argument: " + stressTestArgs.network) - panic(err) + + e2eTest.ETHZRC20 = must(zrc20.NewZRC20(e2eTest.ETHZRC20Addr, e2eTest.ZEVMClient)) + default: + noError(errors.New("invalid network argument: " + stressTestArgs.network)) } // Check zrc20 balance of Deployer address - ethZRC20Balance, err := e2eTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress) - if err != nil { - panic(err) - } + ethZRC20Balance := must(e2eTest.ETHZRC20.BalanceOf(nil, local.DeployerAddress)) fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) //Pre-approve ETH withdraw on ZEVM - fmt.Printf("approving ETH ZRC20...\n") + fmt.Println("approving ETH ZRC20...") ethZRC20 := e2eTest.ETHZRC20 - tx, err := ethZRC20.Approve(e2eTest.ZEVMAuth, e2eTest.ETHZRC20Addr, big.NewInt(1e18)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(ctx, e2eTest.ZEVMClient, tx, logger, e2eTest.ReceiptTimeout) + tx := must(ethZRC20.Approve(e2eTest.ZEVMAuth, e2eTest.ETHZRC20Addr, big.NewInt(1e18))) + + receipt := utils.MustWaitForTxReceipt(e2eTest.Ctx, e2eTest.ZEVMClient, tx, logger, e2eTest.ReceiptTimeout) fmt.Printf("eth zrc20 approve receipt: status %d\n", receipt.Status) // Get current nonce on zevm for DeployerAddress - Need to keep track of nonce at client level - blockNum, err := e2eTest.ZEVMClient.BlockNumber(context.Background()) - if err != nil { - panic(err) - } + blockNum := must(e2eTest.ZEVMClient.BlockNumber(ctx)) // #nosec G701 e2eTest - always in range - nonce, err := e2eTest.ZEVMClient.NonceAt(context.Background(), local.DeployerAddress, big.NewInt(int64(blockNum))) - if err != nil { - panic(err) - } + nonce := must(e2eTest.ZEVMClient.NonceAt(ctx, local.DeployerAddress, big.NewInt(int64(blockNum)))) // #nosec G701 e2e - always in range zevmNonce = big.NewInt(int64(nonce)) @@ -256,24 +222,22 @@ func WithdrawCCtx(runner *runner.E2ERunner) { } } -func EchoNetworkMetrics(runner *runner.E2ERunner) { - ticker := time.NewTicker(time.Second * StatInterval) - var queue = make([]uint64, 0) - var numTicks = 0 - var totalMinedTxns = uint64(0) - var previousMinedTxns = uint64(0) - chainID, err := getChainID(runner.EVMClient) - - if err != nil { - panic(err) - } +func EchoNetworkMetrics(r *runner.E2ERunner) { + var ( + ticker = time.NewTicker(time.Second * StatInterval) + queue = make([]uint64, 0) + numTicks int + totalMinedTxns uint64 + previousMinedTxns uint64 + chainID = must(getChainID(r.EVMClient)) + ) for { select { case <-ticker.C: numTicks++ // Get all pending outbound transactions - cctxResp, err := runner.CctxClient.ListPendingCctx( + cctxResp, err := r.CctxClient.ListPendingCctx( context.Background(), &crosschaintypes.QueryListPendingCctxRequest{ ChainId: chainID.Int64(), @@ -297,7 +261,7 @@ func EchoNetworkMetrics(runner *runner.E2ERunner) { } // // Get all trackers - trackerResp, err := runner.CctxClient.OutboundTrackerAll( + trackerResp, err := r.CctxClient.OutboundTrackerAll( context.Background(), &crosschaintypes.QueryAllOutboundTrackerRequest{}, ) @@ -337,21 +301,22 @@ func EchoNetworkMetrics(runner *runner.E2ERunner) { } } -func WithdrawETHZRC20(runner *runner.E2ERunner) { +func WithdrawETHZRC20(r *runner.E2ERunner) { defer func() { zevmNonce.Add(zevmNonce, big.NewInt(1)) }() - ethZRC20 := runner.ETHZRC20 + ethZRC20 := r.ETHZRC20 + r.ZEVMAuth.Nonce = zevmNonce - runner.ZEVMAuth.Nonce = zevmNonce - _, err := ethZRC20.Withdraw(runner.ZEVMAuth, local.DeployerAddress.Bytes(), big.NewInt(100)) - if err != nil { - panic(err) - } + must(ethZRC20.Withdraw(r.ZEVMAuth, local.DeployerAddress.Bytes(), big.NewInt(100))) } // Get ETH based chain ID func getChainID(client *ethclient.Client) (*big.Int, error) { return client.ChainID(context.Background()) } + +func must[T any](v T, err error) T { + return testutil.Must(v, err) +} diff --git a/cmd/zetatool/filterdeposit/evm.go b/cmd/zetatool/filterdeposit/evm.go index dadaeb4377..f2cea39b99 100644 --- a/cmd/zetatool/filterdeposit/evm.go +++ b/cmd/zetatool/filterdeposit/evm.go @@ -119,7 +119,6 @@ func GetHashListSegment( endBlock uint64, tssAddress string, cfg *config.Config) ([]Deposit, error) { - deposits := make([]Deposit, 0) connectorAddress := common.HexToAddress(cfg.ConnectorAddress) connectorContract, err := zetaconnector.NewZetaConnectorNonEth(connectorAddress, client) diff --git a/contrib/rpctest/main.go b/contrib/rpctest/main.go index 50d55468ba..a9cc1fb405 100644 --- a/contrib/rpctest/main.go +++ b/contrib/rpctest/main.go @@ -252,9 +252,7 @@ func main() { fmt.Printf(" receipt block number: %d\n", receipt.BlockNumber) fmt.Printf(" receipt transaction index: %d\n", receipt.TransactionIndex) fmt.Printf(" receipt contract address: %s\n", receipt.ContractAddress.Hex()) - } - } type EthClient struct { diff --git a/e2e/contracts/contextapp/bindings.go b/e2e/contracts/contextapp/bindings.go index e3246d6be5..6b077d4020 100644 --- a/e2e/contracts/contextapp/bindings.go +++ b/e2e/contracts/contextapp/bindings.go @@ -28,8 +28,7 @@ var ( ) func init() { - err := json.Unmarshal(ContextAppJSON, &ContextAppContract) - if err != nil { + if err := json.Unmarshal(ContextAppJSON, &ContextAppContract); err != nil { panic(err) } diff --git a/e2e/e2etests/helpers.go b/e2e/e2etests/helpers.go index 5980679b63..4dc37498d9 100644 --- a/e2e/e2etests/helpers.go +++ b/e2e/e2etests/helpers.go @@ -8,7 +8,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" ethcommon "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" @@ -26,7 +25,7 @@ func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int) require.NoError(r, err) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - requireReceiptApproved(r, receipt) + utils.RequireTxSuccessful(r, receipt) // mine blocks if testing on regnet stop := r.MineBlocksIfLocalBitcoin() @@ -37,7 +36,7 @@ func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int) require.NoError(r, err) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - requireReceiptApproved(r, receipt) + utils.RequireTxSuccessful(r, receipt) // mine 10 blocks to confirm the withdrawal tx _, err = r.GenerateToAddressIfLocalBitcoin(10, to) @@ -45,7 +44,7 @@ func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int) // get cctx and check status cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - requireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) // get bitcoin tx according to the outTxHash in cctx outTxHash := cctx.GetCurrentOutboundParam().Hash @@ -134,14 +133,3 @@ func parseBitcoinWithdrawArgs(r *runner.E2ERunner, args []string, defaultReceive return receiver, amount } - -// Testify aliases ==========================================> - -func requireReceiptApproved(t require.TestingT, receipt *ethtypes.Receipt) { - require.Equal(t, ethtypes.ReceiptStatusSuccessful, receipt.Status, "receipt status is not successful") -} - -func requireCCTXStatus(t require.TestingT, cctx *crosschaintypes.CrossChainTx, expected crosschaintypes.CctxStatus) { - require.NotNil(t, cctx.CctxStatus) - require.Equal(t, expected, cctx.CctxStatus.Status, "cctx status is not %q", expected.String()) -} diff --git a/e2e/e2etests/test_bitcoin_deposit.go b/e2e/e2etests/test_bitcoin_deposit.go index 6c70f226f4..48460c42be 100644 --- a/e2e/e2etests/test_bitcoin_deposit.go +++ b/e2e/e2etests/test_bitcoin_deposit.go @@ -1,8 +1,7 @@ package e2etests import ( - "fmt" - "strconv" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -10,14 +9,9 @@ import ( ) func TestBitcoinDeposit(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestBitcoinDeposit requires exactly one argument for the amount.") - } + require.Len(r, args, 1) - depositAmount, err := strconv.ParseFloat(args[0], 64) - if err != nil { - panic("Invalid deposit amount specified for TestBitcoinDeposit.") - } + depositAmount := parseFloat(r, args[0]) r.SetBtcAddress(r.Name, false) @@ -26,11 +20,5 @@ func TestBitcoinDeposit(r *runner.E2ERunner, args []string) { // wait for the cctx to be mined cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "deposit") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected mined status; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go b/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go index aaa0725a99..00a9ecb5fe 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go +++ b/e2e/e2etests/test_bitcoin_withdraw_invalid_address.go @@ -1,31 +1,19 @@ package e2etests import ( - "fmt" "math/big" - "strconv" - "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" ) func TestBitcoinWithdrawToInvalidAddress(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestBitcoinWithdrawToInvalidAddress requires exactly one argument for the amount.") - } + require.Len(r, args, 1) - withdrawalAmount, err := strconv.ParseFloat(args[0], 64) - if err != nil { - panic("Invalid withdrawal amount specified for TestBitcoinWithdrawToInvalidAddress.") - } - - withdrawalAmountSat, err := btcutil.NewAmount(withdrawalAmount) - if err != nil { - panic(err) - } - amount := big.NewInt(int64(withdrawalAmountSat)) + withdrawalAmount := parseFloat(r, args[0]) + amount := btcAmountFromFloat64(r, withdrawalAmount) r.SetBtcAddress(r.Name, false) @@ -37,28 +25,20 @@ func withdrawToInvalidAddress(r *runner.E2ERunner, amount *big.Int) { // approve the ZRC20 contract to spend approvalAmount BTC from the deployer address. // the actual amount transferred is provided as test arg BTC, but we approve more to cover withdraw fee tx, err := r.BTCZRC20.Approve(r.ZEVMAuth, r.BTCZRC20Addr, big.NewInt(int64(approvalAmount))) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic(fmt.Errorf("approve receipt status is not 1")) - } + utils.RequireTxSuccessful(r, receipt) // mine blocks if testing on regnet stop := r.MineBlocksIfLocalBitcoin() + defer stop() // withdraw amount provided as test arg BTC from ZRC20 to BTC legacy address // the address "1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3" is for mainnet, not regtest tx, err = r.BTCZRC20.Withdraw(r.ZEVMAuth, []byte("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3"), amount) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 1 { - panic(fmt.Errorf("withdraw receipt status is successful for an invalid BTC address")) - } + require.NoError(r, err) - // stop mining - stop() + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + utils.RequiredTxFailed(r, receipt) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_legacy.go b/e2e/e2etests/test_bitcoin_withdraw_legacy.go index fc2f7b2ca7..57b96034dc 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_legacy.go +++ b/e2e/e2etests/test_bitcoin_withdraw_legacy.go @@ -2,24 +2,22 @@ package e2etests import ( "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" ) func TestBitcoinWithdrawLegacy(r *runner.E2ERunner, args []string) { // check length of arguments - if len(args) != 2 { - panic("TestBitcoinWithdrawLegacy requires two arguments: [receiver, amount]") - } + require.Len(r, args, 2) + r.SetBtcAddress(r.Name, false) // parse arguments and withdraw BTC - defaultReceiver := "mxpYha3UJKUgSwsAz2qYRqaDSwAkKZ3YEY" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) + _, ok := receiver.(*btcutil.AddressPubKeyHash) - if !ok { - panic("Invalid receiver address specified for TestBitcoinWithdrawLegacy.") - } + require.True(r, ok, "Invalid receiver address specified for TestBitcoinWithdrawLegacy.") withdrawBTCZRC20(r, receiver, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_p2sh.go b/e2e/e2etests/test_bitcoin_withdraw_p2sh.go index 97de7675ca..c63a2d2c6b 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_p2sh.go +++ b/e2e/e2etests/test_bitcoin_withdraw_p2sh.go @@ -2,24 +2,22 @@ package e2etests import ( "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" ) func TestBitcoinWithdrawP2SH(r *runner.E2ERunner, args []string) { // check length of arguments - if len(args) != 2 { - panic("TestBitcoinWithdrawP2SH requires two arguments: [receiver, amount]") - } + require.Len(r, args, 2) + r.SetBtcAddress(r.Name, false) // parse arguments and withdraw BTC defaultReceiver := "2N6AoUj3KPS7wNGZXuCckh8YEWcSYNsGbqd" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) _, ok := receiver.(*btcutil.AddressScriptHash) - if !ok { - panic("Invalid receiver address specified for TestBitcoinWithdrawP2SH.") - } + require.True(r, ok, "Invalid receiver address specified for TestBitcoinWithdrawP2SH.") withdrawBTCZRC20(r, receiver, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go b/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go index 79943dc948..5748e0b671 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go +++ b/e2e/e2etests/test_bitcoin_withdraw_p2wsh.go @@ -2,24 +2,21 @@ package e2etests import ( "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" ) func TestBitcoinWithdrawP2WSH(r *runner.E2ERunner, args []string) { - // check length of arguments - if len(args) != 2 { - panic("TestBitcoinWithdrawP2WSH requires two arguments: [receiver, amount]") - } + require.Len(r, args, 2) + r.SetBtcAddress(r.Name, false) // parse arguments and withdraw BTC defaultReceiver := "bcrt1qm9mzhyky4w853ft2ms6dtqdyyu3z2tmrq8jg8xglhyuv0dsxzmgs2f0sqy" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) _, ok := receiver.(*btcutil.AddressWitnessScriptHash) - if !ok { - panic("Invalid receiver address specified for TestBitcoinWithdrawP2WSH.") - } + require.True(r, ok, "Invalid receiver address specified for TestBitcoinWithdrawP2WSH.") withdrawBTCZRC20(r, receiver, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go index 918a4fe6e3..96cdc9ed0a 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go +++ b/e2e/e2etests/test_bitcoin_withdraw_restricted_address.go @@ -1,11 +1,9 @@ package e2etests import ( - "fmt" "math/big" - "strconv" - "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/pkg/chains" @@ -13,20 +11,10 @@ import ( ) func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestBitcoinWithdrawRestricted requires exactly one argument for the amount.") - } + require.Len(r, args, 1) - withdrawalAmount, err := strconv.ParseFloat(args[0], 64) - if err != nil { - panic("Invalid withdrawal amount specified for TestBitcoinWithdrawRestricted.") - } - - withdrawalAmountSat, err := btcutil.NewAmount(withdrawalAmount) - if err != nil { - panic(err) - } - amount := big.NewInt(int64(withdrawalAmountSat)) + withdrawalAmount := parseFloat(r, args[0]) + amount := btcAmountFromFloat64(r, withdrawalAmount) r.SetBtcAddress(r.Name, false) @@ -39,13 +27,9 @@ func withdrawBitcoinRestricted(r *runner.E2ERunner, amount *big.Int) { testutils.RestrictedBtcAddressTest, chains.BitcoinRegtest.ChainId, ) - if err != nil { - panic(err) - } + require.NoError(r, err) // the cctx should be cancelled rawTx := withdrawBTCZRC20(r, addressRestricted, amount) - if len(rawTx.Vout) != 2 { - panic(fmt.Errorf("BTC cancelled outtx rawTx.Vout should have 2 outputs")) - } + require.Len(r, rawTx.Vout, 2, "BTC cancelled outtx rawTx.Vout should have 2 outputs") } diff --git a/e2e/e2etests/test_bitcoin_withdraw_segwit.go b/e2e/e2etests/test_bitcoin_withdraw_segwit.go index 31d5d1176b..2bd763693e 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_segwit.go +++ b/e2e/e2etests/test_bitcoin_withdraw_segwit.go @@ -2,24 +2,21 @@ package e2etests import ( "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" ) func TestBitcoinWithdrawSegWit(r *runner.E2ERunner, args []string) { - // check length of arguments - if len(args) != 2 { - panic("TestBitcoinWithdrawSegWit requires two arguments: [receiver, amount]") - } + require.Len(r, args, 2) + r.SetBtcAddress(r.Name, false) // parse arguments defaultReceiver := r.BTCDeployerAddress.EncodeAddress() receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) _, ok := receiver.(*btcutil.AddressWitnessPubKeyHash) - if !ok { - panic("Invalid receiver address specified for TestBitcoinWithdrawSegWit.") - } + require.True(r, ok, "Invalid receiver address specified for TestBitcoinWithdrawSegWit.") withdrawBTCZRC20(r, receiver, amount) } diff --git a/e2e/e2etests/test_bitcoin_withdraw_taproot.go b/e2e/e2etests/test_bitcoin_withdraw_taproot.go index 5473a947e5..cc1c5feb87 100644 --- a/e2e/e2etests/test_bitcoin_withdraw_taproot.go +++ b/e2e/e2etests/test_bitcoin_withdraw_taproot.go @@ -1,24 +1,22 @@ package e2etests import ( + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/pkg/chains" ) func TestBitcoinWithdrawTaproot(r *runner.E2ERunner, args []string) { - // check length of arguments - if len(args) != 2 { - panic("TestBitcoinWithdrawTaproot requires two arguments: [receiver, amount]") - } + require.Len(r, args, 2) + r.SetBtcAddress(r.Name, false) // parse arguments and withdraw BTC defaultReceiver := "bcrt1pqqqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0sj9hjuh" receiver, amount := parseBitcoinWithdrawArgs(r, args, defaultReceiver) _, ok := receiver.(*chains.AddressTaproot) - if !ok { - panic("Invalid receiver address specified for TestBitcoinWithdrawTaproot.") - } + require.True(r, ok, "Invalid receiver address specified for TestBitcoinWithdrawTaproot.") withdrawBTCZRC20(r, receiver, amount) } diff --git a/e2e/e2etests/test_context_upgrade.go b/e2e/e2etests/test_context_upgrade.go index fc1e7599de..4d06ee84d1 100644 --- a/e2e/e2etests/test_context_upgrade.go +++ b/e2e/e2etests/test_context_upgrade.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -13,30 +14,24 @@ import ( // TestContextUpgrade tests sending ETH on ZetaChain and check context data func TestContextUpgrade(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestContextUpgrade requires exactly one argument for the value.") - } + require.Len(r, args, 1) // parse the value from the provided arguments value, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid value specified for TestContextUpgrade.") - } + require.True(r, ok, "Invalid value specified for TestContextUpgrade.") data := make([]byte, 0, 32) data = append(data, r.ContextAppAddr.Bytes()...) data = append(data, []byte("filler")...) // just to make sure that this is a contract call; signedTx, err := r.SendEther(r.TSSAddress, value, data) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("EVM tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("EVM tx receipt: %d", receipt.Status) r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) r.Logger.Info(" to: %s", signedTx.To().String()) @@ -60,18 +55,13 @@ func TestContextUpgrade(r *runner.E2ERunner, args []string) { r.Logger.Info(" sender: %s", eventIter.Event.Sender.Hex()) r.Logger.Info(" chainid: %d", eventIter.Event.ChainID) r.Logger.Info(" msgsender: %s", eventIter.Event.MsgSender.Hex()) + found = true - if bytes.Compare(eventIter.Event.Origin, r.DeployerAddress.Bytes()) != 0 { - panic("origin mismatch") - } - chainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } - if eventIter.Event.ChainID.Cmp(chainID) != 0 { - panic("chainID mismatch") - } + require.Equal(r, 0, bytes.Compare(eventIter.Event.Origin, r.DeployerAddress.Bytes()), "origin mismatch") + chainID, err := r.EVMClient.ChainID(r.Ctx) + require.NoError(r, err) + require.Equal(r, 0, eventIter.Event.ChainID.Cmp(chainID), "chainID mismatch") } if found { break @@ -79,8 +69,5 @@ func TestContextUpgrade(r *runner.E2ERunner, args []string) { time.Sleep(2 * time.Second) } - if !found { - panic("event not found") - } - + require.True(r, found, "event not found") } diff --git a/e2e/e2etests/test_crosschain_swap.go b/e2e/e2etests/test_crosschain_swap.go index 358e9ba7d7..f1fe6f54aa 100644 --- a/e2e/e2etests/test_crosschain_swap.go +++ b/e2e/e2etests/test_crosschain_swap.go @@ -1,12 +1,13 @@ package e2etests import ( - "fmt" "math/big" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -24,38 +25,30 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { if err != nil { r.Logger.Print("ℹ️create pair error") } + txERC20ZRC20Approve, err := r.ERC20ZRC20.Approve(r.ZEVMAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + txBTCApprove, err := r.BTCZRC20.Approve(r.ZEVMAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) // Fund ZEVMSwapApp with gas ZRC20s txTransferETH, err := r.ETHZRC20.Transfer(r.ZEVMAuth, r.ZEVMSwapAppAddr, big.NewInt(1e7)) - if err != nil { - panic(err) - } + require.NoError(r, err) + txTransferBTC, err := r.BTCZRC20.Transfer(r.ZEVMAuth, r.ZEVMSwapAppAddr, big.NewInt(1e6)) - if err != nil { - panic(err) - } + require.NoError(r, err) - if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txERC20ZRC20Approve, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { - panic("ZRC20 ERC20 approve failed") - } - if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txBTCApprove, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { - panic("btc approve failed") - } - if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txTransferETH, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { - panic("ETH ZRC20 transfer failed") - } - if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txTransferBTC, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { - panic("BTC ZRC20 transfer failed") + ensureTxReceipt := func(tx *ethtypes.Transaction, failMessage string) { + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + utils.RequireTxSuccessful(r, receipt, failMessage) } + ensureTxReceipt(txERC20ZRC20Approve, "ZRC20 ERC20 approve failed") + ensureTxReceipt(txBTCApprove, "BTC approve failed") + ensureTxReceipt(txTransferETH, "ETH ZRC20 transfer failed") + ensureTxReceipt(txTransferBTC, "BTC ZRC20 transfer failed") + // Add 100 erc20 zrc20 liq and 0.001 BTC txAddLiquidity, err := r.UniswapV2Router.AddLiquidity( r.ZEVMAuth, @@ -68,13 +61,8 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.DeployerAddress, big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) - if err != nil { - panic(fmt.Sprintf("Error liq %s", err.Error())) - } - - if receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txAddLiquidity, r.Logger, r.ReceiptTimeout); receipt.Status != 1 { - panic("add liq receipt status is not 1") - } + require.NoError(r, err) + ensureTxReceipt(txAddLiquidity, "add liq failed") // msg would be [ZEVMSwapAppAddr, memobytes] // memobytes is dApp specific; see the contracts/ZEVMSwapApp.sol for details @@ -85,10 +73,8 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.BTCZRC20Addr, []byte(r.BTCDeployerAddress.EncodeAddress()), ) + require.NoError(r, err) - if err != nil { - panic(err) - } r.Logger.Info("memobytes(%d) %x", len(memobytes), memobytes) msg = append(msg, memobytes...) @@ -98,80 +84,52 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { cctx1 := utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) // check the cctx status - if cctx1.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic( - fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx1.CctxStatus.Status.String(), - cctx1.CctxStatus.StatusMessage, - ), - ) - } + utils.RequireCCTXStatus(r, cctx1, types.CctxStatus_OutboundMined) // mine 10 blocks to confirm the outbound tx _, err = r.GenerateToAddressIfLocalBitcoin(10, r.BTCDeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) // mine blocks if testing on regnet stop := r.MineBlocksIfLocalBitcoin() + defer stop() // cctx1 index acts like the inboundHash for the second cctx (the one that withdraws BTC) cctx2 := utils.WaitCctxMinedByInboundHash(r.Ctx, cctx1.Index, r.CctxClient, r.Logger, r.CctxTimeout) // check the cctx status - if cctx2.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx2.CctxStatus.Status.String(), - cctx2.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx2, types.CctxStatus_OutboundMined) r.Logger.Info("cctx2 outbound tx hash %s", cctx2.GetCurrentOutboundParam().Hash) r.Logger.Info("******* Second test: BTC -> ERC20ZRC20") // list deployer utxos utxos, err := r.ListDeployerUTXOs() - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("#utxos %d", len(utxos)) r.Logger.Info("memo address %s", r.ERC20ZRC20Addr) + memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.ERC20ZRC20Addr, r.DeployerAddress.Bytes()) - if err != nil { - panic(err) - } + require.NoError(r, err) + memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) r.Logger.Info("memo length %d", len(memo)) txID, err := r.SendToTSSFromDeployerWithMemo(0.01, utxos[0:1], memo) - if err != nil { - panic(err) - } + require.NoError(r, err) cctx3 := utils.WaitCctxMinedByInboundHash(r.Ctx, txID.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx3.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx3.CctxStatus.Status.String(), - cctx3.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx3, types.CctxStatus_OutboundMined) + r.Logger.Info("cctx3 index %s", cctx3.Index) r.Logger.Info(" inbound tx hash %s", cctx3.InboundParams.ObservedHash) r.Logger.Info(" status %s", cctx3.CctxStatus.Status.String()) r.Logger.Info(" status msg: %s", cctx3.CctxStatus.StatusMessage) cctx4 := utils.WaitCctxMinedByInboundHash(r.Ctx, cctx3.Index, r.CctxClient, r.Logger, r.CctxTimeout) - if cctx4.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected outbound mined status; got %s, message: %s", - cctx3.CctxStatus.Status.String(), - cctx3.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx4, types.CctxStatus_OutboundMined) + r.Logger.Info("cctx4 index %s", cctx4.Index) r.Logger.Info(" outbound tx hash %s", cctx4.GetCurrentOutboundParam().Hash) r.Logger.Info(" status %s", cctx4.CctxStatus.Status.String()) @@ -181,17 +139,14 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { // the following memo will result in a revert in the contract call as targetZRC20 is set to DeployerAddress // which is apparently not a ZRC20 contract; the UNISWAP call will revert memo, err := r.ZEVMSwapApp.EncodeMemo(&bind.CallOpts{}, r.DeployerAddress, r.DeployerAddress.Bytes()) - if err != nil { - panic(err) - } + require.NoError(r, err) + memo = append(r.ZEVMSwapAppAddr.Bytes(), memo...) r.Logger.Info("memo length %d", len(memo)) amount := 0.1 txid, err := r.SendToTSSFromDeployerWithMemo(amount, utxos[1:2], memo) - if err != nil { - panic(err) - } + require.NoError(r, err) cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, txid.String(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.Info("cctx3 index %s", cctx.Index) @@ -199,17 +154,14 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.Logger.Info(" status %s", cctx.CctxStatus.Status.String()) r.Logger.Info(" status msg: %s", cctx.CctxStatus.StatusMessage) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected reverted status; got %s", cctx.CctxStatus.Status.String())) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) + outboundHash, err := chainhash.NewHashFromStr(cctx.GetCurrentOutboundParam().Hash) - if err != nil { - panic(err) - } + require.NoError(r, err) + txraw, err := r.BtcRPCClient.GetRawTransactionVerbose(outboundHash) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("out txid %s", txraw.Txid) for _, vout := range txraw.Vout { r.Logger.Info(" vout %d", vout.N) @@ -218,7 +170,4 @@ func TestCrosschainSwap(r *runner.E2ERunner, _ []string) { r.Logger.Info(" p2wpkh address: %s", utils.ScriptPKToAddress(vout.ScriptPubKey.Hex, r.BitcoinParams)) } } - - // stop mining - stop() } diff --git a/e2e/e2etests/test_deploy_contract.go b/e2e/e2etests/test_deploy_contract.go index 860ae2e0dc..6133942f60 100644 --- a/e2e/e2etests/test_deploy_contract.go +++ b/e2e/e2etests/test_deploy_contract.go @@ -4,6 +4,7 @@ import ( "fmt" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -21,28 +22,20 @@ var deployMap = map[string]deployFunc{ // TestDeployContract deploys the specified contract func TestDeployContract(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + availableContractNames := make([]string, 0, len(deployMap)) for contractName := range deployMap { availableContractNames = append(availableContractNames, contractName) } availableContractNamesMessage := fmt.Sprintf("Available contract names: %v", availableContractNames) - - if len(args) != 1 { - panic( - "TestDeployContract requires exactly one argument for the contract name. " + availableContractNamesMessage, - ) - } contractName := args[0] deployFunc, ok := deployMap[contractName] - if !ok { - panic(fmt.Sprintf("Unknown contract name: %s, %s", contractName, availableContractNamesMessage)) - } + require.True(r, ok, "Unknown contract name: %s, %s", contractName, availableContractNamesMessage) addr, err := deployFunc(r) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Print("%s deployed at %s", contractName, addr.Hex()) } diff --git a/e2e/e2etests/test_donation.go b/e2e/e2etests/test_donation.go index f6d9bac3ff..2347e97e23 100644 --- a/e2e/e2etests/test_donation.go +++ b/e2e/e2etests/test_donation.go @@ -3,6 +3,8 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/pkg/constant" @@ -10,25 +12,18 @@ import ( // TestDonationEther tests donation of ether to the tss address func TestDonationEther(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestDonationEther requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestDonationEther.") - } + require.True(r, ok, "Invalid amount specified for TestDonationEther.") txDonation, err := r.SendEther(r.TSSAddress, amount, []byte(constant.DonationMessage)) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.EVMTransaction(*txDonation, "donation") // check contract deployment receipt receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, txDonation, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "donation") - if receipt.Status != 1 { - panic("donation tx failed") - } + utils.RequireTxSuccessful(r, receipt) } diff --git a/e2e/e2etests/test_erc20_deposit.go b/e2e/e2etests/test_erc20_deposit.go index f550ce4aa7..2f763f34b0 100644 --- a/e2e/e2etests/test_erc20_deposit.go +++ b/e2e/e2etests/test_erc20_deposit.go @@ -3,19 +3,17 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" ) func TestERC20Deposit(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestERC20Deposit requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestERC20Deposit.") - } + require.True(r, ok, "Invalid amount specified for TestERC20Deposit.") hash := r.DepositERC20WithAmountAndMessage(r.DeployerAddress, amount, []byte{}) diff --git a/e2e/e2etests/test_erc20_deposit_refund.go b/e2e/e2etests/test_erc20_deposit_refund.go index 684adf3d6f..ad0a962507 100644 --- a/e2e/e2etests/test_erc20_deposit_refund.go +++ b/e2e/e2etests/test_erc20_deposit_refund.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -17,9 +18,7 @@ import ( func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { // Get the initial balance of the deployer initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Sending a deposit that should revert without a liquidity pool makes the cctx aborted") @@ -27,46 +26,34 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { // send the deposit inboundHash, err := sendInvalidERC20Deposit(r, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) // There is no liquidity pool, therefore the cctx should abort cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, inboundHash, r.CctxClient, r.Logger, r.CctxTimeout) + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Aborted) + require.False(r, cctx.CctxStatus.IsAbortRefunded, "expected cctx status to be not refunded") + r.Logger.CCTX(*cctx, "deposit") - if cctx.CctxStatus.Status != types.CctxStatus_Aborted { - panic(fmt.Sprintf("expected cctx status to be Aborted; got %s", cctx.CctxStatus.Status)) - } + r.Logger.Info("Refunding the cctx via admin") - if cctx.CctxStatus.IsAbortRefunded != false { - panic(fmt.Sprintf("expected cctx status to be not refunded; got %t", cctx.CctxStatus.IsAbortRefunded)) - } + msg := types.NewMsgRefundAbortedCCTX(r.ZetaTxServer.GetAccountAddress(0), cctx.Index, r.DeployerAddress.String()) - r.Logger.Info("Refunding the cctx via admin") - msg := types.NewMsgRefundAbortedCCTX( - r.ZetaTxServer.GetAccountAddress(0), - cctx.Index, - r.DeployerAddress.String()) _, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } + require.NoError(r, err) // Check that the erc20 in the aborted cctx was refunded on ZetaChain newBalance, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + expectedBalance := initialBal.Add(initialBal, amount) - if newBalance.Cmp(expectedBalance) != 0 { - panic( - fmt.Sprintf( - "expected balance to be %s after refund; got %s", - expectedBalance.String(), - newBalance.String(), - ), - ) - } + require.Equal( + r, + 0, + newBalance.Cmp(expectedBalance), + "expected balance to be %s after refund; got %s", + expectedBalance.String(), + newBalance.String(), + ) r.Logger.Info("CCTX has been aborted on ZetaChain") // test refund when there is a liquidity pool @@ -74,67 +61,54 @@ func TestERC20DepositAndCallRefund(r *runner.E2ERunner, _ []string) { r.Logger.Info("Creating the liquidity pool USTD/ZETA") err = createZetaERC20LiquidityPool(r) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Liquidity pool created") erc20Balance, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) // send the deposit amount = big.NewInt(1e7) inboundHash, err = sendInvalidERC20Deposit(r, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + erc20BalanceAfterSend := big.NewInt(0).Sub(erc20Balance, amount) // there is a liquidity pool, therefore the cctx should revert - cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, inboundHash, r.CctxClient, r.Logger, r.CctxTimeout) - // the revert tx creation will fail because the sender, used as the recipient, is not defined in the cctx - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf( - "expected cctx status to be PendingRevert; got %s, aborted message: %s", - cctx.CctxStatus.Status, - cctx.CctxStatus.StatusMessage, - )) - } + cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, inboundHash, r.CctxClient, r.Logger, r.CctxTimeout) + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) // get revert tx revertTxHash := cctx.GetCurrentOutboundParam().Hash receipt, err := r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - if receipt.Status == 0 { - panic("expected the revert tx receipt to have status 1; got 0") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) // check that the erc20 in the reverted cctx was refunded on EVM erc20BalanceAfterRefund, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + // the new balance must be higher than the previous one because of the revert refund - if erc20BalanceAfterSend.Cmp(erc20BalanceAfterRefund) != -1 { - panic(fmt.Sprintf( - "expected balance to be higher after refund than after send %s < %s", - erc20BalanceAfterSend.String(), - erc20BalanceAfterRefund.String(), - )) - } + require.Equal( + r, + -1, + erc20BalanceAfterSend.Cmp(erc20BalanceAfterRefund), + "expected balance to be higher after refund than after send %s < %s", + erc20BalanceAfterSend.String(), + erc20BalanceAfterRefund.String(), + ) + // it must also be lower than the previous balance + the amount because of the gas fee for the revert tx - if erc20BalanceAfterRefund.Cmp(erc20Balance) != -1 { - panic(fmt.Sprintf( - "expected balance to be lower after refund than before send %s < %s", - erc20BalanceAfterRefund.String(), - erc20Balance.String()), - ) - } + require.Equal( + r, + -1, + erc20BalanceAfterRefund.Cmp(erc20Balance), + "expected balance to be lower after refund than before send %s < %s", + erc20BalanceAfterRefund.String(), + erc20Balance.String(), + ) r.Logger.Info("ERC20 CCTX successfully reverted") r.Logger.Info("\tbalance before refund: %s", erc20Balance.String()) diff --git a/e2e/e2etests/test_erc20_deposit_restricted_address.go b/e2e/e2etests/test_erc20_deposit_restricted_address.go index 1823f9236d..758da5a969 100644 --- a/e2e/e2etests/test_erc20_deposit_restricted_address.go +++ b/e2e/e2etests/test_erc20_deposit_restricted_address.go @@ -4,20 +4,17 @@ import ( "math/big" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/zetaclient/testutils" ) func TestERC20DepositRestricted(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestERC20DepositRestricted requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestERC20DepositRestricted.") - } + require.True(r, ok) // deposit ERC20 to restricted address r.DepositERC20WithAmountAndMessage(ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest), amount, []byte{}) diff --git a/e2e/e2etests/test_erc20_multiple_deposits.go b/e2e/e2etests/test_erc20_multiple_deposits.go index b09c363c8d..a99642f356 100644 --- a/e2e/e2etests/test_erc20_multiple_deposits.go +++ b/e2e/e2etests/test_erc20_multiple_deposits.go @@ -1,11 +1,11 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -13,24 +13,17 @@ import ( ) func TestMultipleERC20Deposit(r *runner.E2ERunner, args []string) { - if len(args) != 2 { - panic("TestMultipleERC20Deposit requires exactly two arguments: the deposit amount and the number of deposits.") - } + require.Len(r, args, 2) depositAmount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid deposit amount specified for TestMultipleERC20Deposit.") - } + require.True(r, ok) numberOfDeposits, ok := big.NewInt(0).SetString(args[1], 10) - if !ok || numberOfDeposits.Int64() < 1 { - panic("Invalid number of deposits specified for TestMultipleERC20Deposit.") - } + require.True(r, ok) + require.NotZero(r, numberOfDeposits.Int64()) initialBal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) txhash := multipleDeposits(r, depositAmount, numberOfDeposits) cctxs := utils.WaitCctxsMinedByInboundHash( @@ -41,51 +34,39 @@ func TestMultipleERC20Deposit(r *runner.E2ERunner, args []string) { r.Logger, r.CctxTimeout, ) - if len(cctxs) != 3 { - panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) - } + require.Len(r, cctxs, 3) // check new balance is increased by amount * count bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + diff := big.NewInt(0).Sub(bal, initialBal) total := depositAmount.Mul(depositAmount, numberOfDeposits) - if diff.Cmp(total) != 0 { - panic(fmt.Sprintf("balance difference is not correct: %d", diff.Int64())) - } + + require.Equal(r, 0, diff.Cmp(total), "balance difference is not correct") } func multipleDeposits(r *runner.E2ERunner, amount, count *big.Int) ethcommon.Hash { // deploy depositor depositorAddr, _, depositor, err := testcontract.DeployDepositor(r.EVMAuth, r.EVMClient, r.ERC20CustodyAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) fullAmount := big.NewInt(0).Mul(amount, count) // approve tx, err := r.ERC20.Approve(r.EVMAuth, depositorAddr, fullAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) // deposit tx, err = depositor.RunDeposits(r.EVMAuth, r.DeployerAddress.Bytes(), r.ERC20Addr, amount, []byte{}, count) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposits failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("Deposits receipt tx hash: %s", tx.Hash().Hex()) for _, log := range receipt.Logs { diff --git a/e2e/e2etests/test_erc20_multiple_withdraws.go b/e2e/e2etests/test_erc20_multiple_withdraws.go index de13c7b6b8..14bbb176ca 100644 --- a/e2e/e2etests/test_erc20_multiple_withdraws.go +++ b/e2e/e2etests/test_erc20_multiple_withdraws.go @@ -1,10 +1,10 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -12,67 +12,55 @@ import ( ) func TestMultipleERC20Withdraws(r *runner.E2ERunner, args []string) { + require.Len(r, args, 2) + approvedAmount := big.NewInt(1e18) - if len(args) != 2 { - panic( - "TestMultipleWithdraws requires exactly two arguments: the withdrawal amount and the number of withdrawals.", - ) - } withdrawalAmount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok || withdrawalAmount.Cmp(approvedAmount) >= 0 { - panic("Invalid withdrawal amount specified for TestMultipleWithdraws.") - } + require.True(r, ok) + require.Equal( + r, + -1, + withdrawalAmount.Cmp(approvedAmount), + "Invalid withdrawal amount specified for TestMultipleWithdraws.", + ) numberOfWithdrawals, ok := big.NewInt(0).SetString(args[1], 10) - if !ok || numberOfWithdrawals.Int64() < 1 { - panic("Invalid number of withdrawals specified for TestMultipleWithdraws.") - } + require.True(r, ok) + require.NotEmpty(r, numberOfWithdrawals.Int64()) // calculate total withdrawal to ensure it doesn't exceed approved amount. totalWithdrawal := big.NewInt(0).Mul(withdrawalAmount, numberOfWithdrawals) - if totalWithdrawal.Cmp(approvedAmount) >= 0 { - panic("Total withdrawal amount exceeds approved limit.") - } + require.Equal(r, -1, totalWithdrawal.Cmp(approvedAmount), "Total withdrawal amount exceeds approved limit.") // deploy withdrawer withdrawerAddr, _, withdrawer, err := testcontract.DeployWithdrawer(r.ZEVMAuth, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // approve tx, err := r.ERC20ZRC20.Approve(r.ZEVMAuth, withdrawerAddr, approvedAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("ERC20 ZRC20 approve receipt: status %d", receipt.Status) // approve gas token tx, err = r.ETHZRC20.Approve(r.ZEVMAuth, withdrawerAddr, approvedAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve gas token failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) // check the balance bal, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("balance of deployer on ERC20 ZRC20: %d", bal) - if bal.Int64() < totalWithdrawal.Int64() { - panic("not enough ERC20 ZRC20 balance!") - } + require.Less(r, totalWithdrawal.Int64(), bal.Int64(), "not enough ERC20 ZRC20 balance!") // withdraw tx, err = withdrawer.RunWithdraws( @@ -82,13 +70,9 @@ func TestMultipleERC20Withdraws(r *runner.E2ERunner, args []string) { withdrawalAmount, numberOfWithdrawals, ) - if err != nil { - panic(err) - } + require.NoError(r, err) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("withdraw failed") - } + utils.RequireTxSuccessful(r, receipt) cctxs := utils.WaitCctxsMinedByInboundHash( r.Ctx, @@ -98,9 +82,7 @@ func TestMultipleERC20Withdraws(r *runner.E2ERunner, args []string) { r.Logger, r.CctxTimeout, ) - if len(cctxs) != 3 { - panic(fmt.Sprintf("cctxs length is not correct: %d", len(cctxs))) - } + require.Len(r, cctxs, 3) // verify the withdraw value for _, cctx := range cctxs { diff --git a/e2e/e2etests/test_erc20_withdraw.go b/e2e/e2etests/test_erc20_withdraw.go index 3d24b1670a..f2ce31b5c3 100644 --- a/e2e/e2etests/test_erc20_withdraw.go +++ b/e2e/e2etests/test_erc20_withdraw.go @@ -3,34 +3,27 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" ) func TestERC20Withdraw(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + approvedAmount := big.NewInt(1e18) - if len(args) != 1 { - panic("TestERC20Withdraw requires exactly one argument for the withdrawal amount.") - } withdrawalAmount, ok := new(big.Int).SetString(args[0], 10) - if !ok { - panic("Invalid withdrawal amount specified for TestERC20Withdraw.") - } - - if withdrawalAmount.Cmp(approvedAmount) >= 0 { - panic("Withdrawal amount must be less than the approved amount (1e18).") - } + require.True(r, ok, "Invalid withdrawal amount specified for TestERC20Withdraw.") + require.Equal(r, -1, withdrawalAmount.Cmp(approvedAmount)) // approve tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, r.ERC20ZRC20Addr, approvedAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Info("eth zrc20 approve receipt: status %d", receipt.Status) // withdraw @@ -38,5 +31,6 @@ func TestERC20Withdraw(r *runner.E2ERunner, args []string) { // verify the withdraw value cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + verifyTransferAmountFromCCTX(r, cctx, withdrawalAmount.Int64()) } diff --git a/e2e/e2etests/test_eth_deposit.go b/e2e/e2etests/test_eth_deposit.go index 5b06bfe3bc..03da8f6da4 100644 --- a/e2e/e2etests/test_eth_deposit.go +++ b/e2e/e2etests/test_eth_deposit.go @@ -3,20 +3,18 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" ) // TestEtherDeposit tests deposit of ethers func TestEtherDeposit(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestEtherDeposit requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestEtherDeposit.") - } + require.True(r, ok, "Invalid amount specified for TestEtherDeposit.") hash := r.DepositEtherWithAmount(false, amount) // in wei // wait for the cctx to be mined diff --git a/e2e/e2etests/test_eth_deposit_call.go b/e2e/e2etests/test_eth_deposit_call.go index dc6cc5cb32..0d7734fbdb 100644 --- a/e2e/e2etests/test_eth_deposit_call.go +++ b/e2e/e2etests/test_eth_deposit_call.go @@ -1,13 +1,12 @@ package e2etests import ( - "fmt" "math/big" - "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -17,125 +16,91 @@ import ( // TestEtherDepositAndCall tests deposit of ethers calling a example contract func TestEtherDepositAndCall(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestEtherDepositAndCall requires exactly one argument for the amount.") - } + require.Len(r, args, 1) value, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestEtherDepositAndCall.") - } + require.True(r, ok, "Invalid amount specified for TestEtherDepositAndCall.") r.Logger.Info("Deploying example contract") exampleAddr, _, exampleContract, err := testcontract.DeployExample(r.ZEVMAuth, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Example contract deployed") // preparing tx evmClient := r.EVMClient gasLimit := uint64(23000) gasPrice, err := evmClient.SuggestGasPrice(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) data := append(exampleAddr.Bytes(), []byte("hello sailors")...) tx := ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) chainID, err := evmClient.NetworkID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) - if err != nil { - panic(err) - } + require.NoError(r, err) + signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Sending a cross-chain call to example contract") err = evmClient.SendTransaction(r.Ctx, signedTx) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected cctx status to be mined; got %s", cctx.CctxStatus.Status)) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined) // Checking example contract has been called, bar value should be set to amount bar, err := exampleContract.Bar(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if bar.Cmp(value) != 0 { - panic( - fmt.Sprintf( - "cross-chain call failed bar value %s should be equal to amount %s", - bar.String(), - value.String(), - ), - ) - } + require.NoError(r, err) + require.Equal( + r, + 0, + bar.Cmp(value), + "cross-chain call failed bar value %s should be equal to amount %s", + bar.String(), + value.String(), + ) r.Logger.Info("Cross-chain call succeeded") r.Logger.Info("Deploying reverter contract") reverterAddr, _, _, err := testcontract.DeployReverter(r.ZEVMAuth, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Example reverter deployed") // preparing tx for reverter gasPrice, err = evmClient.SuggestGasPrice(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + nonce, err = evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) data = append(reverterAddr.Bytes(), []byte("hello sailors")...) tx = ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) signedTx, err = ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Sending a cross-chain call to reverter contract") err = evmClient.SendTransaction(r.Ctx, signedTx) - if err != nil { - panic(err) - } + require.NoError(r, err) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be reverted; got %s", cctx.CctxStatus.Status)) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) + r.Logger.Info("Cross-chain call to reverter reverted") // check the status message contains revert error hash in case of revert // 0xbfb4ebcf is the hash of "Foo()" - if !strings.Contains(cctx.CctxStatus.StatusMessage, "0xbfb4ebcf") { - panic( - fmt.Sprintf("expected cctx status message to contain revert reason; got %s", cctx.CctxStatus.StatusMessage), - ) - } + require.Contains(r, cctx.CctxStatus.StatusMessage, "0xbfb4ebcf") } diff --git a/e2e/e2etests/test_eth_deposit_liquidity_cap.go b/e2e/e2etests/test_eth_deposit_liquidity_cap.go index a132fdd35e..f64b041478 100644 --- a/e2e/e2etests/test_eth_deposit_liquidity_cap.go +++ b/e2e/e2etests/test_eth_deposit_liquidity_cap.go @@ -1,11 +1,11 @@ package e2etests import ( - "fmt" "math/big" "cosmossdk.io/math" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -15,15 +15,11 @@ import ( // TestDepositEtherLiquidityCap tests depositing Ethers in a context where a liquidity cap is set func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestDepositEtherLiquidityCap requires exactly one argument for the liquidity cap.") - } + require.Len(r, args, 1) liquidityCapArg := math.NewUintFromString(args[0]) supply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) - if err != nil { - panic(err) - } + require.NoError(r, err) liquidityCap := math.NewUintFromBigInt(supply).Add(liquidityCapArg) amountLessThanCap := liquidityCapArg.BigInt().Div(liquidityCapArg.BigInt(), big.NewInt(10)) // 1/10 of the cap @@ -34,63 +30,41 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { liquidityCap, ) res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } - r.Logger.Info("set liquidity cap tx hash: %s", res.TxHash) + require.NoError(r, err) + r.Logger.Info("set liquidity cap tx hash: %s", res.TxHash) r.Logger.Info("Depositing more than liquidity cap should make cctx reverted") + signedTx, err := r.SendEther(r.TSSAddress, amountMoreThanCap, nil) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } + utils.RequireTxSuccessful(r, receipt) + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) + r.Logger.Info("CCTX has been reverted") r.Logger.Info("Depositing less than liquidity cap should still succeed") initialBal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + signedTx, err = r.SendEther(r.TSSAddress, amountLessThanCap, nil) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } + utils.RequireTxSuccessful(r, receipt) + cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - - panic(fmt.Sprintf( - "expected cctx status to be Success; got %s; message: %s; supply: %s; liquidity cap: %s, amountLessThanCap: %s, amountMoreThanCap: %s", - cctx.CctxStatus.Status, - cctx.CctxStatus.StatusMessage, - supply.String(), - liquidityCap.String(), - amountLessThanCap.String(), - amountMoreThanCap.String(), - )) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined) expectedBalance := big.NewInt(0).Add(initialBal, amountLessThanCap) bal, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } - if bal.Cmp(expectedBalance) != 0 { + require.NoError(r, err) + require.Equal(r, 0, bal.Cmp(expectedBalance)) - panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) - } r.Logger.Info("Deposit succeeded") r.Logger.Info("Removing the liquidity cap") @@ -99,32 +73,33 @@ func TestDepositEtherLiquidityCap(r *runner.E2ERunner, args []string) { r.ETHZRC20Addr.Hex(), math.ZeroUint(), ) + res, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("remove liquidity cap tx hash: %s", res.TxHash) + initialBal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + signedTx, err = r.SendEther(r.TSSAddress, amountMoreThanCap, nil) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } + utils.RequireTxSuccessful(r, receipt) + utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) expectedBalance = big.NewInt(0).Add(initialBal, amountMoreThanCap) bal, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } - if bal.Cmp(expectedBalance) != 0 { - panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) - } + require.NoError(r, err) + require.Equal(r, + 0, + bal.Cmp(expectedBalance), + "expected balance to be %s; got %s", + expectedBalance.String(), + bal.String(), + ) + r.Logger.Info("New deposit succeeded") } diff --git a/e2e/e2etests/test_eth_deposit_refund.go b/e2e/e2etests/test_eth_deposit_refund.go index 2de41965ea..394ffdd8e4 100644 --- a/e2e/e2etests/test_eth_deposit_refund.go +++ b/e2e/e2etests/test_eth_deposit_refund.go @@ -1,12 +1,12 @@ package e2etests import ( - "fmt" "math/big" ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -14,109 +14,74 @@ import ( ) func TestEtherDepositAndCallRefund(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestEtherDepositAndCallRefund requires exactly one argument for the amount.") - } + require.Len(r, args, 1) value, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestEtherDepositAndCallRefund.") - } + require.True(r, ok, "Invalid amount specified for TestEtherDepositAndCallRefund.") evmClient := r.EVMClient nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) gasLimit := uint64(23000) // in units gasPrice, err := evmClient.SuggestGasPrice(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) data := append(r.BTCZRC20Addr.Bytes(), []byte("hello sailors")...) // this data tx := ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) chainID, err := evmClient.NetworkID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) - if err != nil { - panic(err) - } + require.NoError(r, err) signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(chainID), deployerPrivkey) - if err != nil { - panic(err) - } + require.NoError(r, err) + err = evmClient.SendTransaction(r.Ctx, signedTx) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("EVM tx sent: %s; to %s, nonce %d", signedTx.Hash().String(), signedTx.To().Hex(), signedTx.Nonce()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("EVM tx receipt: %d", receipt.Status) r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) r.Logger.Info(" to: %s", signedTx.To().String()) r.Logger.Info(" value: %d", signedTx.Value()) r.Logger.Info(" block num: %d", receipt.BlockNumber) - func() { - cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - r.Logger.Info("cctx status message: %s", cctx.CctxStatus.StatusMessage) - revertTxHash := cctx.GetCurrentOutboundParam().Hash - r.Logger.Info("EVM revert tx receipt: status %d", receipt.Status) - - tx, _, err := r.EVMClient.TransactionByHash(r.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - receipt, err := r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(revertTxHash)) - if err != nil { - panic(err) - } - - printTxInfo := func() { - // debug info when test fails - r.Logger.Info(" tx: %+v", tx) - r.Logger.Info(" receipt: %+v", receipt) - r.Logger.Info("cctx http://localhost:1317/zeta-chain/crosschain/cctx/%s", cctx.Index) - } - - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - printTxInfo() - panic(fmt.Sprintf("expected cctx status to be PendingRevert; got %s", cctx.CctxStatus.Status)) - } - - if receipt.Status == 0 { - printTxInfo() - panic("expected the revert tx receipt to have status 1; got 0") - } - - if *tx.To() != r.DeployerAddress { - printTxInfo() - panic(fmt.Sprintf("expected tx to %s; got %s", r.DeployerAddress.Hex(), tx.To().Hex())) - } - - // the received value must be lower than the original value because of the paid fees for the revert tx - // we check that the value is still greater than 0 - if tx.Value().Cmp(value) != -1 || tx.Value().Cmp(big.NewInt(0)) != 1 { - printTxInfo() - panic( - fmt.Sprintf( - "expected tx value %s; should be non-null and lower than %s", - tx.Value().String(), - value.String(), - ), - ) - } - - r.Logger.Info("REVERT tx receipt: %d", receipt.Status) - r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) - r.Logger.Info(" to: %s", tx.To().String()) - r.Logger.Info(" value: %s", tx.Value().String()) - r.Logger.Info(" block num: %d", receipt.BlockNumber) - }() + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.Info("cctx status message: %s", cctx.CctxStatus.StatusMessage) + revertTxHash := cctx.GetCurrentOutboundParam().Hash + r.Logger.Info("EVM revert tx receipt: status %d", receipt.Status) + + tx, _, err = r.EVMClient.TransactionByHash(r.Ctx, ethcommon.HexToHash(revertTxHash)) + require.NoError(r, err) + + receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(revertTxHash)) + require.NoError(r, err) + + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) + utils.RequireTxSuccessful(r, receipt) + + require.Equal(r, r.DeployerAddress, *tx.To(), "expected tx to %s; got %s", r.DeployerAddress.Hex(), tx.To().Hex()) + + // the received value must be lower than the original value because of the paid fees for the revert tx + // we check that the value is still greater than 0 + invariant := tx.Value().Cmp(value) != -1 || tx.Value().Cmp(big.NewInt(0)) != 1 + require.False( + r, + invariant, + "expected tx value %s; should be non-null and lower than %s", + tx.Value().String(), + value.String(), + ) + + r.Logger.Info("REVERT tx receipt: %d", receipt.Status) + r.Logger.Info(" tx hash: %s", receipt.TxHash.String()) + r.Logger.Info(" to: %s", tx.To().String()) + r.Logger.Info(" value: %s", tx.Value().String()) + r.Logger.Info(" block num: %d", receipt.BlockNumber) } diff --git a/e2e/e2etests/test_eth_withdraw.go b/e2e/e2etests/test_eth_withdraw.go index 5a71ec65fb..798704fe39 100644 --- a/e2e/e2etests/test_eth_withdraw.go +++ b/e2e/e2etests/test_eth_withdraw.go @@ -3,51 +3,46 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) -// TestEtherWithdraw tests the withdraw of ether +// TestEtherWithdraw tests the withdrawal of ether func TestEtherWithdraw(r *runner.E2ERunner, args []string) { - r.Logger.Info("TestEtherWithdraw") + require.Len(r, args, 1) approvedAmount := big.NewInt(1e18) - if len(args) != 1 { - panic("TestEtherWithdraw requires exactly one argument for the withdrawal amount.") - } - withdrawalAmount, ok := new(big.Int).SetString(args[0], 10) - if !ok { - panic("Invalid withdrawal amount specified for TestEtherWithdraw.") - } - - if withdrawalAmount.Cmp(approvedAmount) >= 0 { - panic("Withdrawal amount must be less than the approved amount (1e18).") - } + require.True(r, ok, "Invalid withdrawal amount specified for TestEtherWithdraw.") + require.Equal( + r, + -1, + withdrawalAmount.Cmp(approvedAmount), + "Withdrawal amount must be less than the approved amount (1e18).", + ) // approve tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, r.ETHZRC20Addr, approvedAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.EVMTransaction(*tx, "approve") receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.EVMReceipt(*receipt, "approve") // withdraw tx = r.WithdrawEther(withdrawalAmount) - // verify the withdraw value + // verify the withdrawal value cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic("cctx status is not outbound mined") - } + + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) r.Logger.Info("TestEtherWithdraw completed") } diff --git a/e2e/e2etests/test_eth_withdraw_restricted_address.go b/e2e/e2etests/test_eth_withdraw_restricted_address.go index 8f17cb4edb..793bfc42c5 100644 --- a/e2e/e2etests/test_eth_withdraw_restricted_address.go +++ b/e2e/e2etests/test_eth_withdraw_restricted_address.go @@ -4,6 +4,7 @@ import ( "math/big" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -13,54 +14,47 @@ import ( // TestEtherWithdrawRestricted tests the withdrawal to a restricted receiver address func TestEtherWithdrawRestricted(r *runner.E2ERunner, args []string) { + require.Len(r, args, 1) + approvedAmount := big.NewInt(1e18) - if len(args) != 1 { - panic("TestEtherWithdrawRestricted requires exactly one argument for the withdrawal amount.") - } withdrawalAmount, ok := new(big.Int).SetString(args[0], 10) - if !ok { - panic("Invalid withdrawal amount specified for TestEtherWithdrawRestricted.") - } - - if withdrawalAmount.Cmp(approvedAmount) >= 0 { - panic("Withdrawal amount must be less than the approved amount (1e18).") - } + require.True(r, ok) + require.True( + r, + withdrawalAmount.Cmp(approvedAmount) <= 0, + "Withdrawal amount must be less than the approved amount (1e18)", + ) // approve tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, r.ETHZRC20Addr, approvedAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.EVMTransaction(*tx, "approve") receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.EVMReceipt(*receipt, "approve") // withdraw restrictedAddress := ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest) tx, err = r.ETHZRC20.Withdraw(r.ZEVMAuth, restrictedAddress.Bytes(), withdrawalAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.EVMTransaction(*tx, "withdraw to restricted address") receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("withdraw failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.EVMReceipt(*receipt, "withdraw") r.Logger.ZRC20Withdrawal(r.ETHZRC20, *receipt, "withdraw") - // verify the withdraw value + // verify the withdrawal value cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic("cctx status is not outbound mined") - } + + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) // the cctx should be cancelled with zero value verifyTransferAmountFromCCTX(r, cctx, 0) diff --git a/e2e/e2etests/test_message_passing_evm_to_zevm.go b/e2e/e2etests/test_message_passing_evm_to_zevm.go index bedfd50965..4a7ac7f906 100644 --- a/e2e/e2etests/test_message_passing_evm_to_zevm.go +++ b/e2e/e2etests/test_message_passing_evm_to_zevm.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -14,81 +15,56 @@ import ( ) func TestMessagePassingEVMtoZEVM(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingEVMtoZEVM requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingEVMtoZEVM.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingEVMtoZEVM.") // Set destination details zEVMChainID, err := r.ZEVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) destinationAddress := r.ZevmTestDAppAddr // Contract call originates from EVM chain tx, err := r.ZetaEth.Approve(r.EVMAuth, r.EvmTestDAppAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("approve tx failed") - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Info("Approve tx receipt: %d", receipt.Status) testDAppEVM, err := testdapp.NewTestDApp(r.EvmTestDAppAddr, r.EVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // Get ZETA balance on ZEVM TestDApp previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) previousBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EVMAuth.From) - if err != nil { - panic(err) - } + require.NoError(r, err) // Call the SendHelloWorld function on the EVM dapp Contract which would in turn create a new send, to be picked up by the zeta-clients // set Do revert to false which adds a message to signal the ZEVM zetaReceiver to not revert the transaction tx, err = testDAppEVM.SendHelloWorld(r.EVMAuth, destinationAddress, zEVMChainID, amount, false) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) // New inbound message picked up by zeta-clients and voted on by observers to initiate a contract call on zEVM cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { - panic("expected cctx to be outbound_mined") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_OutboundMined) + r.Logger.Info(fmt.Sprintf("🔄 Cctx mined for contract call chain zevm %s", cctx.Index)) // On finalization the Fungible module calls the onReceive function which in turn calls the onZetaMessage function on the destination contract receipt, err = r.ZEVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) testDAppZEVM, err := testdapp.NewTestDApp(r.ZevmTestDAppAddr, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // Check event emitted receivedHelloWorldEvent := false @@ -99,33 +75,15 @@ func TestMessagePassingEVMtoZEVM(r *runner.E2ERunner, args []string) { receivedHelloWorldEvent = true } } - if !receivedHelloWorldEvent { - panic(fmt.Sprintf("expected HelloWorld event, logs: %+v", receipt.Logs)) - } + require.True(r, receivedHelloWorldEvent, "expected HelloWorld event") // Check ZETA balance on ZEVM TestDApp and check new balance is previous balance + amount newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } - if newBalanceZEVM.Cmp(big.NewInt(0).Add(previousBalanceZEVM, amount)) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - big.NewInt(0).Add(previousBalanceZEVM, amount).String(), - newBalanceZEVM.String()), - ) - } + require.NoError(r, err) + require.Equal(r, 0, newBalanceZEVM.Cmp(big.NewInt(0).Add(previousBalanceZEVM, amount))) // Check ZETA balance on EVM TestDApp and check new balance is previous balance - amount newBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EVMAuth.From) - if err != nil { - panic(err) - } - if newBalanceEVM.Cmp(big.NewInt(0).Sub(previousBalanceEVM, amount)) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - big.NewInt(0).Sub(previousBalanceEVM, amount).String(), - newBalanceEVM.String()), - ) - } + require.NoError(r, err) + require.Equal(r, 0, newBalanceEVM.Cmp(big.NewInt(0).Sub(previousBalanceEVM, amount))) } diff --git a/e2e/e2etests/test_message_passing_evm_to_zevm_revert.go b/e2e/e2etests/test_message_passing_evm_to_zevm_revert.go index 3c12711aed..99a49fba56 100644 --- a/e2e/e2etests/test_message_passing_evm_to_zevm_revert.go +++ b/e2e/e2etests/test_message_passing_evm_to_zevm_revert.go @@ -1,11 +1,11 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -14,57 +14,43 @@ import ( ) func TestMessagePassingEVMtoZEVMRevert(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingEVMtoZEVMRevert requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingEVMtoZEVMRevert.") - } + require.True(r, ok) // Set destination details zEVMChainID, err := r.ZEVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) destinationAddress := r.ZevmTestDAppAddr // Contract call originates from EVM chain tx, err := r.ZetaEth.Approve(r.EVMAuth, r.EvmTestDAppAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("Approve tx receipt: %d", receipt.Status) testDAppEVM, err := testdapp.NewTestDApp(r.EvmTestDAppAddr, r.EVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // Get ZETA balance before test previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) // Call the SendHelloWorld function on the EVM dapp Contract which would in turn create a new send, to be picked up by the zeta-clients // set Do revert to true which adds a message to signal the ZEVM zetaReceiver to revert the transaction tx, err = testDAppEVM.SendHelloWorld(r.EVMAuth, destinationAddress, zEVMChainID, amount, true) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) @@ -72,18 +58,13 @@ func TestMessagePassingEVMtoZEVMRevert(r *runner.E2ERunner, args []string) { // New inbound message picked up by zeta-clients and voted on by observers to initiate a contract call on zEVM which would revert the transaction // A revert transaction is created and gets fialized on the original sender chain. cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Reverted { - panic("expected cctx to be reverted") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Reverted) // On finalization the Tss address calls the onRevert function which in turn calls the onZetaRevert function on the sender contract receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) + receivedHelloWorldEvent := false for _, log := range receipt.Logs { _, err := testDAppEVM.ParseRevertedHelloWorldEvent(*log) @@ -92,37 +73,36 @@ func TestMessagePassingEVMtoZEVMRevert(r *runner.E2ERunner, args []string) { receivedHelloWorldEvent = true } } - if !receivedHelloWorldEvent { - panic(fmt.Sprintf("expected Reverted HelloWorld event, logs: %+v", receipt.Logs)) - } + require.True(r, receivedHelloWorldEvent, "expected Reverted HelloWorld event") // Check ZETA balance on ZEVM TestDApp and check new balance is previous balance newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } - if newBalanceZEVM.Cmp(previousBalanceZEVM) != 0 { - panic( - fmt.Sprintf("expected new balance to be %s, got %s", previousBalanceZEVM.String(), newBalanceZEVM.String()), - ) - } + require.NoError(r, err) + require.Equal( + r, + 0, + newBalanceZEVM.Cmp(previousBalanceZEVM), + "expected new balance to be %s, got %s", + previousBalanceZEVM.String(), + newBalanceZEVM.String(), + ) // Check ZETA balance on EVM TestDApp and check new balance is between previous balance and previous balance + amount // New balance is increased because ZETA are sent from the sender but sent back to the contract // New balance is less than previous balance + amount because of the gas fee to pay newBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceAndAmountEVM := big.NewInt(0).Add(previousBalanceEVM, amount) // check higher than previous balance and lower than previous balance + amount - if newBalanceEVM.Cmp(previousBalanceEVM) <= 0 || newBalanceEVM.Cmp(previousBalanceAndAmountEVM) > 0 { - panic(fmt.Sprintf( - "expected new balance to be between %s and %s, got %s", - previousBalanceEVM.String(), - previousBalanceAndAmountEVM.String(), - newBalanceEVM.String()), - ) - } + invariant := newBalanceEVM.Cmp(previousBalanceEVM) <= 0 || newBalanceEVM.Cmp(previousBalanceAndAmountEVM) > 0 + require.False( + r, + invariant, + "expected new balance to be between %s and %s, got %s", + previousBalanceEVM.String(), + previousBalanceAndAmountEVM.String(), + newBalanceEVM.String(), + ) } diff --git a/e2e/e2etests/test_message_passing_evm_to_zevm_revert_fail.go b/e2e/e2etests/test_message_passing_evm_to_zevm_revert_fail.go index 352fe959a8..a767f619ad 100644 --- a/e2e/e2etests/test_message_passing_evm_to_zevm_revert_fail.go +++ b/e2e/e2etests/test_message_passing_evm_to_zevm_revert_fail.go @@ -1,10 +1,10 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdappnorevert" "github.com/zeta-chain/zetacore/e2e/runner" @@ -13,14 +13,10 @@ import ( ) func TestMessagePassingEVMtoZEVMRevertFail(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingEVMtoZEVMRevertFail requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingEVMtoZEVMRevertFail.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingEVMtoZEVMRevertFail.") // Deploying a test contract not containing a logic for reverting the cctx testDappNoRevertEVMAddr, tx, testDappNoRevertEVM, err := testdappnorevert.DeployTestDAppNoRevert( @@ -29,87 +25,66 @@ func TestMessagePassingEVMtoZEVMRevertFail(r *runner.E2ERunner, args []string) { r.ConnectorEthAddr, r.ZetaEthAddr, ) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("TestDAppNoRevertEVM deployed at: %s", testDappNoRevertEVMAddr.Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + utils.RequireTxSuccessful(r, receipt) + r.Logger.EVMReceipt(*receipt, "deploy TestDAppNoRevert") - if receipt.Status == 0 { - panic("deploy TestDAppNoRevert failed") - } // Set destination details zEVMChainID, err := r.ZEVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) destinationAddress := r.ZevmTestDAppAddr // Contract call originates from EVM chain tx, err = r.ZetaEth.Approve(r.EVMAuth, testDappNoRevertEVMAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("Approve tx receipt: %d", receipt.Status) // Get ZETA balance before test previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, testDappNoRevertEVMAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) // Send message with doRevert tx, err = testDappNoRevertEVM.SendHelloWorld(r.EVMAuth, destinationAddress, zEVMChainID, amount, true) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("TestDAppNoRevert.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) // New inbound message picked up by zeta-clients and voted on by observers to initiate a contract call on zEVM which would revert the transaction - // A revert transaction is created and gets fialized on the original sender chain. + // A revert transaction is created and gets finalized on the original sender chain. cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Aborted { - panic("expected cctx to be reverted") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Aborted) // Check ZETA balance on ZEVM TestDApp and check new balance is previous balance newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } - if newBalanceZEVM.Cmp(previousBalanceZEVM) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - previousBalanceZEVM.String(), - newBalanceZEVM.String()), - ) - } + require.NoError(r, err) + require.Equal( + r, + 0, + newBalanceZEVM.Cmp(previousBalanceZEVM), + "expected new balance to be %s, got %s", + previousBalanceZEVM.String(), + newBalanceZEVM.String(), + ) // Check ZETA balance on EVM TestDApp and check new balance is previous balance newBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, testDappNoRevertEVMAddr) - if err != nil { - panic(err) - } - if newBalanceEVM.Cmp(previousBalanceEVM) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - previousBalanceEVM.String(), - newBalanceEVM.String()), - ) - } + require.NoError(r, err) + require.Equal(r, 0, newBalanceEVM.Cmp(previousBalanceEVM)) } diff --git a/e2e/e2etests/test_message_passing_external_chains.go b/e2e/e2etests/test_message_passing_external_chains.go index 5a6fed227e..317665920b 100644 --- a/e2e/e2etests/test_message_passing_external_chains.go +++ b/e2e/e2etests/test_message_passing_external_chains.go @@ -1,10 +1,10 @@ package e2etests import ( - "fmt" "math/big" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" "github.com/zeta-chain/zetacore/e2e/runner" @@ -16,32 +16,25 @@ import ( // TODO: Use two external EVM chains for these tests // https://github.com/zeta-chain/node/issues/2185 func TestMessagePassingExternalChains(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassing requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassing.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassing.") chainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Approving ConnectorEth to spend deployer's ZetaEth") auth := r.EVMAuth + tx, err := r.ZetaEth.Approve(auth, r.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("Approve tx receipt: %d", receipt.Status) r.Logger.Info("Calling ConnectorEth.Send") tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ @@ -52,15 +45,13 @@ func TestMessagePassingExternalChains(r *runner.E2ERunner, args []string) { ZetaValueAndGas: amount, ZetaParams: nil, }) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) r.Logger.Info(" Logs:") for _, log := range receipt.Logs { @@ -75,22 +66,14 @@ func TestMessagePassingExternalChains(r *runner.E2ERunner, args []string) { r.Logger.Info("Waiting for ConnectorEth.Send CCTX to be mined...") r.Logger.Info(" INTX hash: %s", receipt.TxHash.String()) + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected cctx status to be %s; got %s, message %s", - cctxtypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_OutboundMined) + receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) + for _, log := range receipt.Logs { event, err := r.ConnectorEth.ParseZetaReceived(*log) if err == nil { @@ -98,9 +81,9 @@ func TestMessagePassingExternalChains(r *runner.E2ERunner, args []string) { r.Logger.Info(" Dest Addr: %s", event.DestinationAddress) r.Logger.Info(" Zeta Value: %d", event.ZetaValue) r.Logger.Info(" src chainid: %d", event.SourceChainId) - if event.ZetaValue.Cmp(cctx.GetCurrentOutboundParam().Amount.BigInt()) != 0 { - panic("Zeta value mismatch") - } + + comp := event.ZetaValue.Cmp(cctx.GetCurrentOutboundParam().Amount.BigInt()) + require.Equal(r, 0, comp, "Zeta value mismatch") } } } diff --git a/e2e/e2etests/test_message_passing_external_chains_revert.go b/e2e/e2etests/test_message_passing_external_chains_revert.go index fee09b3bb0..37146a4c78 100644 --- a/e2e/e2etests/test_message_passing_external_chains_revert.go +++ b/e2e/e2etests/test_message_passing_external_chains_revert.go @@ -5,6 +5,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -16,65 +17,48 @@ import ( // TODO: Use two external EVM chains for these tests // https://github.com/zeta-chain/node/issues/2185 func TestMessagePassingRevertSuccessExternalChains(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingRevertSuccess requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingRevertSuccess.") - } + require.True(r, ok) chainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) auth := r.EVMAuth tx, err := r.ZetaEth.Approve(auth, r.EvmTestDAppAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Info("Approve tx receipt: %d", receipt.Status) r.Logger.Info("Calling TestDApp.SendHello on contract address %s", r.EvmTestDAppAddr.Hex()) testDApp, err := testdapp.NewTestDApp(r.EvmTestDAppAddr, r.EVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + + res2, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{Denom: "azeta"}) + require.NoError(r, err) - res2, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{ - Denom: "azeta", - }) - if err != nil { - panic(err) - } r.Logger.Info("$$$ Before: SUPPLY OF AZETA: %d", res2.Amount.Amount) tx, err = testDApp.SendHelloWorld(auth, r.EvmTestDAppAddr, chainID, amount, true) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("TestDApp.SendHello tx receipt: status %d", receipt.Status) cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Reverted { - panic("expected cctx to be reverted") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Reverted) + outTxHash := cctx.GetCurrentOutboundParam().Hash receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(outTxHash)) - if err != nil { - panic(err) - } + require.NoError(r, err) + for _, log := range receipt.Logs { event, err := r.ConnectorEth.ParseZetaReverted(*log) if err == nil { @@ -85,12 +69,10 @@ func TestMessagePassingRevertSuccessExternalChains(r *runner.E2ERunner, args []s r.Logger.Info(" Message: %x", event.Message) } } - res3, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{ - Denom: "azeta", - }) - if err != nil { - panic(err) - } + + res3, err := r.BankClient.SupplyOf(r.Ctx, &banktypes.QuerySupplyOfRequest{Denom: "azeta"}) + require.NoError(r, err) + r.Logger.Info("$$$ After: SUPPLY OF AZETA: %d", res3.Amount.Amount.BigInt()) r.Logger.Info("$$$ Diff: SUPPLY OF AZETA: %d", res3.Amount.Amount.Sub(res2.Amount.Amount).BigInt()) } diff --git a/e2e/e2etests/test_message_passing_external_chains_revert_fail.go b/e2e/e2etests/test_message_passing_external_chains_revert_fail.go index e9bdeb0c7e..3950a8cdd5 100644 --- a/e2e/e2etests/test_message_passing_external_chains_revert_fail.go +++ b/e2e/e2etests/test_message_passing_external_chains_revert_fail.go @@ -4,6 +4,8 @@ import ( "math/big" ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" "github.com/zeta-chain/zetacore/e2e/runner" @@ -15,32 +17,26 @@ import ( // TODO: Use two external EVM chains for these tests // https://github.com/zeta-chain/node/issues/2185 func TestMessagePassingRevertFailExternalChains(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingRevertFail requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingRevertFail.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingRevertFail.") chainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) auth := r.EVMAuth tx, err := r.ZetaEth.Approve(auth, r.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("Approve tx receipt: %d", receipt.Status) r.Logger.Info("Calling ConnectorEth.Send") + tx, err = r.ConnectorEth.Send(auth, zetaconnectoreth.ZetaInterfacesSendInput{ DestinationChainId: chainID, DestinationAddress: r.DeployerAddress.Bytes(), @@ -51,14 +47,13 @@ func TestMessagePassingRevertFailExternalChains(r *runner.E2ERunner, args []stri ZetaValueAndGas: amount, ZetaParams: nil, }) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("ConnectorEth.Send tx hash: %s", tx.Hash().Hex()) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Info("ConnectorEth.Send tx receipt: status %d", receipt.Status) r.Logger.Info(" Logs:") for _, log := range receipt.Logs { @@ -74,14 +69,9 @@ func TestMessagePassingRevertFailExternalChains(r *runner.E2ERunner, args []stri // expect revert tx to fail cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } + require.NoError(r, err) + // expect revert tx to fail as well - if receipt.Status != 0 { - panic("expected revert tx to fail") - } - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Aborted { - panic("expected cctx to be aborted") - } + require.Equal(r, ethtypes.ReceiptStatusFailed, receipt.Status) + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Aborted) } diff --git a/e2e/e2etests/test_message_passing_zevm_to_evm.go b/e2e/e2etests/test_message_passing_zevm_to_evm.go index 0e7c888be2..dde161f2f9 100644 --- a/e2e/e2etests/test_message_passing_zevm_to_evm.go +++ b/e2e/e2etests/test_message_passing_zevm_to_evm.go @@ -1,11 +1,11 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -14,96 +14,65 @@ import ( ) func TestMessagePassingZEVMtoEVM(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingZEVMtoEVM requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingZEVMtoEVM.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingZEVMtoEVM.") // Set destination details EVMChainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + destinationAddress := r.EvmTestDAppAddr // Contract call originates from ZEVM chain r.ZEVMAuth.Value = amount tx, err := r.WZeta.Deposit(r.ZEVMAuth) - if err != nil { - panic(err) - } + require.NoError(r, err) r.ZEVMAuth.Value = big.NewInt(0) r.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta deposit") - if receipt.Status == 0 { - panic("deposit failed") - } + utils.RequireTxSuccessful(r, receipt) tx, err = r.WZeta.Approve(r.ZEVMAuth, r.ZevmTestDAppAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta approve") - if receipt.Status == 0 { - panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) testDAppZEVM, err := testdapp.NewTestDApp(r.ZevmTestDAppAddr, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // Get previous balances previousBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZEVMAuth.From) - if err != nil { - panic(err) - } + require.NoError(r, err) // Call the SendHelloWorld function on the ZEVM dapp Contract which would in turn create a new send, to be picked up by the zetanode evm hooks // set Do revert to false which adds a message to signal the EVM zetaReceiver to not revert the transaction tx, err = testDAppZEVM.SendHelloWorld(r.ZEVMAuth, destinationAddress, EVMChainID, amount, false) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) // Transaction is picked up by the zetanode evm hooks and a new contract call is initiated on the EVM chain cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_OutboundMined { - panic("expected cctx to be outbound_mined") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_OutboundMined) // On finalization the Tss calls the onReceive function which in turn calls the onZetaMessage function on the destination contract. receipt, err = r.EVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) testDAppEVM, err := testdapp.NewTestDApp(r.EvmTestDAppAddr, r.EVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) receivedHelloWorldEvent := false for _, log := range receipt.Logs { @@ -113,38 +82,35 @@ func TestMessagePassingZEVMtoEVM(r *runner.E2ERunner, args []string) { receivedHelloWorldEvent = true } } - if !receivedHelloWorldEvent { - panic(fmt.Sprintf("expected HelloWorld event, logs: %+v", receipt.Logs)) - } + require.True(r, receivedHelloWorldEvent, "expected HelloWorld event") // Check ZETA balance on EVM TestDApp and check new balance between previous balance and previous balance + amount // Contract receive less than the amount because of the gas fee to pay newBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceAndAmountEVM := big.NewInt(0).Add(previousBalanceEVM, amount) // check higher than previous balance and lower than previous balance + amount - if newBalanceEVM.Cmp(previousBalanceEVM) <= 0 || newBalanceEVM.Cmp(previousBalanceAndAmountEVM) > 0 { - panic(fmt.Sprintf( - "expected new balance to be between %s and %s, got %s", - previousBalanceEVM.String(), - previousBalanceAndAmountEVM.String(), - newBalanceEVM.String()), - ) - } + invariant := newBalanceEVM.Cmp(previousBalanceEVM) <= 0 || newBalanceEVM.Cmp(previousBalanceAndAmountEVM) > 0 + require.False( + r, + invariant, + "expected new balance to be between %s and %s, got %s", + previousBalanceEVM.String(), + previousBalanceAndAmountEVM.String(), + newBalanceEVM.String(), + ) // Check ZETA balance on ZEVM TestDApp and check new balance is previous balance - amount newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZEVMAuth.From) - if err != nil { - panic(err) - } - if newBalanceZEVM.Cmp(big.NewInt(0).Sub(previousBalanceZEVM, amount)) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - big.NewInt(0).Sub(previousBalanceZEVM, amount).String(), - newBalanceZEVM.String()), - ) - } + require.NoError(r, err) + require.Equal( + r, + 0, + newBalanceZEVM.Cmp(big.NewInt(0).Sub(previousBalanceZEVM, amount)), + "expected new balance to be %s, got %s", + big.NewInt(0).Sub(previousBalanceZEVM, amount).String(), + newBalanceZEVM.String(), + ) } diff --git a/e2e/e2etests/test_message_passing_zevm_to_evm_revert.go b/e2e/e2etests/test_message_passing_zevm_to_evm_revert.go index 0badfefdcb..85f81f0a04 100644 --- a/e2e/e2etests/test_message_passing_zevm_to_evm_revert.go +++ b/e2e/e2etests/test_message_passing_zevm_to_evm_revert.go @@ -1,11 +1,11 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdapp" "github.com/zeta-chain/zetacore/e2e/runner" @@ -14,91 +14,64 @@ import ( ) func TestMessagePassingZEVMtoEVMRevert(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingZEVMtoEVMRevert requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingZEVMtoEVMRevert.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingZEVMtoEVMRevert.") // Set destination details EVMChainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + destinationAddress := r.EvmTestDAppAddr // Contract call originates from ZEVM chain r.ZEVMAuth.Value = amount tx, err := r.WZeta.Deposit(r.ZEVMAuth) - if err != nil { - panic(err) - } + require.NoError(r, err) r.ZEVMAuth.Value = big.NewInt(0) r.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta deposit") - if receipt.Status == 0 { - panic("deposit failed") - } + utils.RequireTxSuccessful(r, receipt) tx, err = r.WZeta.Approve(r.ZEVMAuth, r.ZevmTestDAppAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta approve") - if receipt.Status == 0 { - panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) testDAppZEVM, err := testdapp.NewTestDApp(r.ZevmTestDAppAddr, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) // Get ZETA balance before test previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) // Call the SendHelloWorld function on the ZEVM dapp Contract which would in turn create a new send, to be picked up by the zetanode evm hooks // set Do revert to true which adds a message to signal the EVM zetaReceiver to revert the transaction tx, err = testDAppZEVM.SendHelloWorld(r.ZEVMAuth, destinationAddress, EVMChainID, amount, true) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("TestDApp.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) // New inbound message picked up by zetanode evm hooks and processed directly to initiate a contract call on EVM which would revert the transaction cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Reverted { - panic("expected cctx to be reverted") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Reverted) // On finalization the Fungible module calls the onRevert function which in turn calls the onZetaRevert function on the sender contract receipt, err = r.ZEVMClient.TransactionReceipt(r.Ctx, ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash)) - if err != nil { - panic(err) - } - if receipt.Status != 1 { - panic("tx failed") - } + require.NoError(r, err) + utils.RequireTxSuccessful(r, receipt) receivedHelloWorldEvent := false for _, log := range receipt.Logs { @@ -108,39 +81,28 @@ func TestMessagePassingZEVMtoEVMRevert(r *runner.E2ERunner, args []string) { receivedHelloWorldEvent = true } } - if !receivedHelloWorldEvent { - panic(fmt.Sprintf("expected Reverted HelloWorld event, logs: %+v", receipt.Logs)) - } + require.True(r, receivedHelloWorldEvent, "expected Reverted HelloWorld event") // Check ZETA balance on ZEVM TestDApp and check new balance is between previous balance and previous balance + amount // New balance is increased because ZETA are sent from the sender but sent back to the contract // Contract receive less than the amount because of the gas fee to pay newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.ZevmTestDAppAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) + previousBalanceAndAmountZEVM := big.NewInt(0).Add(previousBalanceZEVM, amount) // check higher than previous balance and lower than previous balance + amount - if newBalanceZEVM.Cmp(previousBalanceZEVM) <= 0 || newBalanceZEVM.Cmp(previousBalanceAndAmountZEVM) > 0 { - panic(fmt.Sprintf( - "expected new balance to be between %s and %s, got %s", - previousBalanceZEVM.String(), - previousBalanceAndAmountZEVM.String(), - newBalanceZEVM.String()), - ) - } + invariant := newBalanceZEVM.Cmp(previousBalanceZEVM) <= 0 || newBalanceZEVM.Cmp(previousBalanceAndAmountZEVM) > 0 + require.False(r, + invariant, + "expected new balance to be between %s and %s, got %s", + previousBalanceZEVM.String(), + previousBalanceAndAmountZEVM.String(), + newBalanceZEVM.String(), + ) // Check ZETA balance on EVM TestDApp and check new balance is previous balance newBalanceEVM, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.EvmTestDAppAddr) - if err != nil { - panic(err) - } - if newBalanceEVM.Cmp(previousBalanceEVM) != 0 { - panic(fmt.Sprintf( - "expected new balance to be %s, got %s", - previousBalanceEVM.String(), - newBalanceEVM.String()), - ) - } + require.NoError(r, err) + require.Equal(r, 0, newBalanceEVM.Cmp(previousBalanceEVM), "expected new balance to be equal to previous balance") } diff --git a/e2e/e2etests/test_message_passing_zevm_to_evm_revert_fail.go b/e2e/e2etests/test_message_passing_zevm_to_evm_revert_fail.go index b822199af6..cc22db23a3 100644 --- a/e2e/e2etests/test_message_passing_zevm_to_evm_revert_fail.go +++ b/e2e/e2etests/test_message_passing_zevm_to_evm_revert_fail.go @@ -1,10 +1,10 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testdappnorevert" "github.com/zeta-chain/zetacore/e2e/runner" @@ -13,14 +13,10 @@ import ( ) func TestMessagePassingZEVMtoEVMRevertFail(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestMessagePassingZEVMtoEVMRevertFail requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestMessagePassingZEVMtoEVMRevertFail.") - } + require.True(r, ok, "Invalid amount specified for TestMessagePassingZEVMtoEVMRevertFail.") // Deploying a test contract not containing a logic for reverting the cctx testDappNoRevertAddr, tx, testDappNoRevert, err := testdappnorevert.DeployTestDAppNoRevert( @@ -29,83 +25,64 @@ func TestMessagePassingZEVMtoEVMRevertFail(r *runner.E2ERunner, args []string) { r.ConnectorZEVMAddr, r.WZetaAddr, ) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("TestDAppNoRevert deployed at: %s", testDappNoRevertAddr.Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "deploy TestDAppNoRevert") - if receipt.Status == 0 { - panic("deploy TestDAppNoRevert failed") - } + utils.RequireTxSuccessful(r, receipt) // Set destination details EVMChainID, err := r.EVMClient.ChainID(r.Ctx) - if err != nil { - panic(err) - } + require.NoError(r, err) + destinationAddress := r.EvmTestDAppAddr // Contract call originates from ZEVM chain r.ZEVMAuth.Value = amount tx, err = r.WZeta.Deposit(r.ZEVMAuth) - if err != nil { - panic(err) - } + require.NoError(r, err) r.ZEVMAuth.Value = big.NewInt(0) r.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta deposit") - if receipt.Status == 0 { - panic("deposit failed") - } + utils.RequireTxSuccessful(r, receipt) tx, err = r.WZeta.Approve(r.ZEVMAuth, testDappNoRevertAddr, amount) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "wzeta approve") - if receipt.Status == 0 { - panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) // Get previous balances to check funds are not minted anywhere when aborted previousBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, testDappNoRevertAddr) - if err != nil { - panic(err) - } + require.NoError(r, err) // Send message with doRevert tx, err = testDappNoRevert.SendHelloWorld(r.ZEVMAuth, destinationAddress, EVMChainID, amount, true) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("TestDAppNoRevert.SendHello tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) - } + utils.RequireTxSuccessful(r, receipt) // The revert tx will fail, the cctx state should be aborted cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != cctxtypes.CctxStatus_Aborted { - panic("expected cctx to be reverted") - } + utils.RequireCCTXStatus(r, cctx, cctxtypes.CctxStatus_Aborted) // Check the funds are not minted to the contract as the cctx has been aborted newBalanceZEVM, err := r.WZeta.BalanceOf(&bind.CallOpts{}, testDappNoRevertAddr) - if err != nil { - panic(err) - } - if newBalanceZEVM.Cmp(previousBalanceZEVM) != 0 { - panic( - fmt.Sprintf("expected new balance to be %s, got %s", previousBalanceZEVM.String(), newBalanceZEVM.String()), - ) - } + require.NoError(r, err) + require.Equal(r, + 0, + newBalanceZEVM.Cmp(previousBalanceZEVM), + "expected new balance to be %s, got %s", + previousBalanceZEVM.String(), + newBalanceZEVM.String(), + ) } diff --git a/e2e/e2etests/test_migrate_chain_support.go b/e2e/e2etests/test_migrate_chain_support.go index f39bcbc2a3..848335ddef 100644 --- a/e2e/e2etests/test_migrate_chain_support.go +++ b/e2e/e2etests/test_migrate_chain_support.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/fatih/color" + "github.com/stretchr/testify/require" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/zetacore/e2e/runner" @@ -44,9 +45,8 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { // create runner for the new EVM and set it up newRunner, err := configureEVM2(r) - if err != nil { - panic(err) - } + require.NoError(r, err) + newRunner.SetupEVM(false, false) // mint some ERC20 @@ -59,21 +59,16 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { // update the chain params to set up the chain chainParams := getNewEVMChainParams(newRunner) adminAddr, err := newRunner.ZetaTxServer.GetAccountAddressFromName(utils.FungibleAdminName) - if err != nil { - panic(err) - } + require.NoError(r, err) + _, err = newRunner.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, observertypes.NewMsgUpdateChainParams( adminAddr, chainParams, )) - if err != nil { - panic(err) - } + require.NoError(r, err) // setup the gas token - if err != nil { - panic(err) - } + require.NoError(r, err) _, err = newRunner.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, fungibletypes.NewMsgDeployFungibleCoinZRC20( adminAddr, "", @@ -84,26 +79,19 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { coin.CoinType_Gas, 100000, )) - if err != nil { - panic(err) - } + require.NoError(r, err) // set the gas token in the runner ethZRC20Addr, err := newRunner.SystemContract.GasCoinZRC20ByChainId( &bind.CallOpts{}, big.NewInt(chainParams.ChainId), ) - if err != nil { - panic(err) - } - if (ethZRC20Addr == ethcommon.Address{}) { - panic("eth zrc20 not found") - } + require.NoError(r, err) + require.NotEqual(r, ethcommon.Address{}, ethZRC20Addr) + newRunner.ETHZRC20Addr = ethZRC20Addr ethZRC20, err := zrc20.NewZRC20(ethZRC20Addr, newRunner.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) newRunner.ETHZRC20 = ethZRC20 // set the chain nonces for the new chain @@ -113,9 +101,7 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { 0, 0, )) - if err != nil { - panic(err) - } + require.NoError(r, err) // deactivate the previous chain chainParams = observertypes.GetDefaultGoerliLocalnetChainParams() @@ -124,15 +110,11 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { adminAddr, chainParams, )) - if err != nil { - panic(err) - } + require.NoError(r, err) // restart ZetaClient to pick up the new chain r.Logger.Print("🔄 restarting ZetaClient to pick up the new chain") - if err := restartZetaClient(); err != nil { - panic(err) - } + require.NoError(r, restartZetaClient()) // wait 10 set for the chain to start time.Sleep(10 * time.Second) @@ -141,18 +123,14 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { txWithdraw, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), big.NewInt(10000000000000000)) if err == nil { receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, txWithdraw, r.Logger, r.ReceiptTimeout) - if receipt.Status == 1 { - panic("withdraw should have failed on the previous chain") - } + utils.RequiredTxFailed(r, receipt) } // test cross-chain functionalities on the new network // we use a Go routine to manually mine blocks because Anvil network only mine blocks on tx by default // we need automatic block mining to get the necessary confirmations for the cross-chain functionalities stopMining, err := newRunner.AnvilMineBlocks(EVM2RPCURL, 3) - if err != nil { - panic(err) - } + require.NoError(r, err) // deposit Ethers and ERC20 on ZetaChain etherAmount := big.NewInt(1e18) @@ -166,14 +144,7 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { tx := newRunner.WithdrawZeta(amount, true) cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "zeta withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Errorf( - "expected cctx status to be %s; got %s, message %s", - crosschaintypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) TestEtherWithdraw(newRunner, []string{"50000000000000000"}) @@ -193,32 +164,24 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) { 18, 100000, )) - if err != nil { - panic(err) - } + require.NoError(r, err) // retrieve zrc20 and cctx from event whitelistCCTXIndex, err := txserver.FetchAttributeFromTxResponse(res, "whitelist_cctx_index") - if err != nil { - panic(err) - } + require.NoError(r, err) erc20zrc20Addr, err := txserver.FetchAttributeFromTxResponse(res, "zrc20_address") - if err != nil { - panic(err) - } + require.NoError(r, err) // wait for the whitelist cctx to be mined newRunner.WaitForMinedCCTXFromIndex(whitelistCCTXIndex) // set erc20 zrc20 contract address - if !ethcommon.IsHexAddress(erc20zrc20Addr) { - panic(fmt.Errorf("invalid contract address: %s", erc20zrc20Addr)) - } + require.True(r, ethcommon.IsHexAddress(erc20zrc20Addr), "invalid contract address: %s", erc20zrc20Addr) + erc20ZRC20, err := zrc20.NewZRC20(ethcommon.HexToAddress(erc20zrc20Addr), newRunner.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + newRunner.ERC20ZRC20 = erc20ZRC20 // deposit ERC20 on ZetaChain diff --git a/e2e/e2etests/test_pause_zrc20.go b/e2e/e2etests/test_pause_zrc20.go index dbe5182e80..1495a7ac60 100644 --- a/e2e/e2etests/test_pause_zrc20.go +++ b/e2e/e2etests/test_pause_zrc20.go @@ -1,9 +1,10 @@ package e2etests import ( - "fmt" "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/contracts/vault" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -16,26 +17,20 @@ func TestPauseZRC20(r *runner.E2ERunner, _ []string) { // Setup vault used to test zrc20 interactions r.Logger.Info("Deploying vault") vaultAddr, _, vaultContract, err := vault.DeployVault(r.ZEVMAuth, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + // Approving vault to spend ZRC20 tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, vaultAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("Vault approval should succeed") - } + utils.RequireTxSuccessful(r, receipt) + tx, err = r.ERC20ZRC20.Approve(r.ZEVMAuth, vaultAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("Vault approval should succeed") - } + utils.RequireTxSuccessful(r, receipt) // Pause ETH ZRC20 r.Logger.Info("Pausing ETH") @@ -44,86 +39,68 @@ func TestPauseZRC20(r *runner.E2ERunner, _ []string) { []string{r.ETHZRC20Addr.Hex()}, ) res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msgPause) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("pause zrc20 tx hash: %s", res.TxHash) // Fetch and check pause status fcRes, err := r.FungibleClient.ForeignCoins(r.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ Index: r.ETHZRC20Addr.Hex(), }) - if err != nil { - panic(err) - } - if !fcRes.GetForeignCoins().Paused { - panic("ETH should be paused") - } + require.NoError(r, err) + require.True(r, fcRes.GetForeignCoins().Paused, "ETH should be paused") + r.Logger.Info("ETH is paused") // Try operations with ETH ZRC20 r.Logger.Info("Can no longer do operations on ETH ZRC20") + tx, err = r.ETHZRC20.Transfer(r.ZEVMAuth, sample.EthAddress(), big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 1 { - panic("transfer should fail") - } + utils.RequiredTxFailed(r, receipt) + tx, err = r.ETHZRC20.Burn(r.ZEVMAuth, big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 1 { - panic("burn should fail") - } + utils.RequiredTxFailed(r, receipt) // Operation on a contract that interact with ETH ZRC20 should fail r.Logger.Info("Vault contract can no longer interact with ETH ZRC20: %s", r.ETHZRC20Addr.Hex()) tx, err = vaultContract.Deposit(r.ZEVMAuth, r.ETHZRC20Addr, big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 1 { - panic("deposit should fail") - } + utils.RequiredTxFailed(r, receipt) + r.Logger.Info("Operations all failed") // Check we can still interact with ERC20 ZRC20 r.Logger.Info("Check other ZRC20 can still be operated") + tx, err = r.ERC20ZRC20.Transfer(r.ZEVMAuth, sample.EthAddress(), big.NewInt(1e3)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("ERC20 ZRC20 transfer should succeed") - } + utils.RequireTxSuccessful(r, receipt) + tx, err = vaultContract.Deposit(r.ZEVMAuth, r.ERC20ZRC20Addr, big.NewInt(1e3)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("ERC20 ZRC20 vault deposit should succeed") - } + utils.RequireTxSuccessful(r, receipt) // Check deposit revert when paused signedTx, err := r.SendEther(r.TSSAddress, big.NewInt(1e17), nil) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit eth tx failed") - } + utils.RequireTxSuccessful(r, receipt) + cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, signedTx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_Reverted { - panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_Reverted) + r.Logger.Info("CCTX has been reverted") // Unpause ETH ZRC20 @@ -133,51 +110,40 @@ func TestPauseZRC20(r *runner.E2ERunner, _ []string) { []string{r.ETHZRC20Addr.Hex()}, ) res, err = r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msgUnpause) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("unpause zrc20 tx hash: %s", res.TxHash) // Fetch and check pause status fcRes, err = r.FungibleClient.ForeignCoins(r.Ctx, &fungibletypes.QueryGetForeignCoinsRequest{ Index: r.ETHZRC20Addr.Hex(), }) - if err != nil { - panic(err) - } - if fcRes.GetForeignCoins().Paused { - panic("ETH should be unpaused") - } + require.NoError(r, err) + require.False(r, fcRes.GetForeignCoins().Paused, "ETH should be unpaused") + r.Logger.Info("ETH is unpaused") // Try operations with ETH ZRC20 r.Logger.Info("Can do operations on ETH ZRC20 again") + tx, err = r.ETHZRC20.Transfer(r.ZEVMAuth, sample.EthAddress(), big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("transfer should succeed") - } + utils.RequireTxSuccessful(r, receipt) + tx, err = r.ETHZRC20.Burn(r.ZEVMAuth, big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("burn should succeed") - } + utils.RequireTxSuccessful(r, receipt) // Can deposit tokens into the vault again tx, err = vaultContract.Deposit(r.ZEVMAuth, r.ETHZRC20Addr, big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit should succeed") - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Info("Operations all succeeded") } diff --git a/e2e/e2etests/test_rate_limiter.go b/e2e/e2etests/test_rate_limiter.go index db8d67f348..446d49a6b2 100644 --- a/e2e/e2etests/test_rate_limiter.go +++ b/e2e/e2etests/test_rate_limiter.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/zeta-chain/zetacore/e2e/runner" @@ -55,47 +56,31 @@ func TestRateLimiter(r *runner.E2ERunner, _ []string) { erc20Amount := big.NewInt(1e6) // approve tokens for the tests - if err := approveTokens(r); err != nil { - panic(err) - } + require.NoError(r, approveTokens(r)) // add liquidity in the pool to prevent high slippage in WZETA/gas pair - if err := addZetaGasLiquidity(r); err != nil { - panic(err) - } + require.NoError(r, addZetaGasLiquidity(r)) // Set the rate limiter to 0.5ZETA per 10 blocks // These rate limiter flags will only allow to process 1 withdraw per 10 blocks r.Logger.Info("setting up rate limiter flags") - if err := setupRateLimiterFlags(r, rateLimiterFlags); err != nil { - panic(err) - } + require.NoError(r, setupRateLimiterFlags(r, rateLimiterFlags)) // Test with rate limiter // TODO: define proper assertion to check the rate limiter is working // https://github.com/zeta-chain/node/issues/2090 r.Logger.Print("rate limiter enabled") - if err := createAndWaitWithdraws(r, withdrawTypeZETA, zetaAmount); err != nil { - panic(err) - } - if err := createAndWaitWithdraws(r, withdrawTypeETH, ethAmount); err != nil { - panic(err) - } - if err := createAndWaitWithdraws(r, withdrawTypeERC20, erc20Amount); err != nil { - panic(err) - } + require.NoError(r, createAndWaitWithdraws(r, withdrawTypeZETA, zetaAmount)) + require.NoError(r, createAndWaitWithdraws(r, withdrawTypeZETA, ethAmount)) + require.NoError(r, createAndWaitWithdraws(r, withdrawTypeZETA, erc20Amount)) // Disable rate limiter r.Logger.Info("disabling rate limiter") - if err := setupRateLimiterFlags(r, crosschaintypes.RateLimiterFlags{Enabled: false}); err != nil { - panic(err) - } + require.NoError(r, setupRateLimiterFlags(r, crosschaintypes.RateLimiterFlags{Enabled: false})) // Test without rate limiter again and try again ZETA withdraws r.Logger.Print("rate limiter disabled") - if err := createAndWaitWithdraws(r, withdrawTypeZETA, zetaAmount); err != nil { - panic(err) - } + require.NoError(r, createAndWaitWithdraws(r, withdrawTypeZETA, zetaAmount)) } // createAndWaitWithdraws performs RateLimiterWithdrawNumber withdraws @@ -107,7 +92,6 @@ func createAndWaitWithdraws(r *runner.E2ERunner, withdrawType withdrawType, with // Perform RateLimiterWithdrawNumber withdraws to log time for completion txs := make([]*ethtypes.Transaction, rateLimiterWithdrawNumber) for i := 0; i < rateLimiterWithdrawNumber; i++ { - // create a new withdraw depending on the type switch withdrawType { case withdrawTypeZETA: diff --git a/e2e/e2etests/test_stress_btc_deposit.go b/e2e/e2etests/test_stress_btc_deposit.go index 51e1b8857f..b6c3e7c6a8 100644 --- a/e2e/e2etests/test_stress_btc_deposit.go +++ b/e2e/e2etests/test_stress_btc_deposit.go @@ -2,10 +2,10 @@ package e2etests import ( "fmt" - "strconv" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/zeta-chain/zetacore/e2e/runner" @@ -15,19 +15,10 @@ import ( // TestStressBTCDeposit tests the stressing deposit of BTC func TestStressBTCDeposit(r *runner.E2ERunner, args []string) { - if len(args) != 2 { - panic("TestStressBTCDeposit requires exactly two arguments: the deposit amount and the number of deposits.") - } + require.Len(r, args, 2) - depositAmount, err := strconv.ParseFloat(args[1], 64) - if err != nil { - panic("Invalid deposit amount specified for TestStressBTCDeposit.") - } - - numDeposits, err := strconv.Atoi(args[1]) - if err != nil || numDeposits < 1 { - panic("Invalid number of deposits specified for TestStressBTCDeposit.") - } + depositAmount := parseFloat(r, args[0]) + numDeposits := parseInt(r, args[1]) r.SetBtcAddress(r.Name, false) @@ -42,15 +33,10 @@ func TestStressBTCDeposit(r *runner.E2ERunner, args []string) { txHash := r.DepositBTCWithAmount(depositAmount) r.Logger.Print("index %d: starting deposit, tx hash: %s", i, txHash.String()) - eg.Go(func() error { - return monitorBTCDeposit(r, txHash, i, time.Now()) - }) + eg.Go(func() error { return monitorBTCDeposit(r, txHash, i, time.Now()) }) } - // wait for all the deposits to complete - if err := eg.Wait(); err != nil { - panic(err) - } + require.NoError(r, eg.Wait()) r.Logger.Print("all deposits completed") } diff --git a/e2e/e2etests/test_stress_btc_withdraw.go b/e2e/e2etests/test_stress_btc_withdraw.go index 28ccb77178..08c5844448 100644 --- a/e2e/e2etests/test_stress_btc_withdraw.go +++ b/e2e/e2etests/test_stress_btc_withdraw.go @@ -3,11 +3,11 @@ package e2etests import ( "fmt" "math/big" - "strconv" "time" "github.com/btcsuite/btcutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/zeta-chain/zetacore/e2e/runner" @@ -17,21 +17,10 @@ import ( // TestStressBTCWithdraw tests the stressing withdraw of btc func TestStressBTCWithdraw(r *runner.E2ERunner, args []string) { - if len(args) != 2 { - panic( - "TestStressBTCWithdraw requires exactly two arguments: the withdrawal amount and the number of withdrawals.", - ) - } - - withdrawalAmount, err := strconv.ParseFloat(args[0], 64) - if err != nil { - panic("Invalid withdrawal amount specified for TestStressBTCWithdraw.") - } + require.Len(r, args, 2) - numWithdraws, err := strconv.Atoi(args[1]) - if err != nil || numWithdraws < 1 { - panic("Invalid number of withdrawals specified for TestStressBTCWithdraw.") - } + withdrawalAmount := parseFloat(r, args[0]) + numWithdraws := parseInt(r, args[1]) r.SetBtcAddress(r.Name, false) @@ -41,9 +30,7 @@ func TestStressBTCWithdraw(r *runner.E2ERunner, args []string) { var eg errgroup.Group satAmount, err := btcutil.NewAmount(withdrawalAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) // send the withdraws for i := 0; i < numWithdraws; i++ { @@ -53,25 +40,16 @@ func TestStressBTCWithdraw(r *runner.E2ERunner, args []string) { []byte(r.BTCDeployerAddress.EncodeAddress()), big.NewInt(int64(satAmount)), ) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - //r.Logger.Info("index %d: withdraw evm tx failed", index) - panic(fmt.Sprintf("index %d: withdraw btc tx %s failed", i, tx.Hash().Hex())) - } + utils.RequireTxSuccessful(r, receipt) r.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) - eg.Go(func() error { - return monitorBTCWithdraw(r, tx, i, time.Now()) - }) + eg.Go(func() error { return monitorBTCWithdraw(r, tx, i, time.Now()) }) } - // wait for all the withdraws to complete - if err := eg.Wait(); err != nil { - panic(err) - } + require.NoError(r, eg.Wait()) r.Logger.Print("all withdraws completed") } diff --git a/e2e/e2etests/test_stress_eth_deposit.go b/e2e/e2etests/test_stress_eth_deposit.go index f3b1e94dc8..9e0208f7e3 100644 --- a/e2e/e2etests/test_stress_eth_deposit.go +++ b/e2e/e2etests/test_stress_eth_deposit.go @@ -3,10 +3,10 @@ package e2etests import ( "fmt" "math/big" - "strconv" "time" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/zeta-chain/zetacore/e2e/runner" @@ -16,19 +16,12 @@ import ( // TestStressEtherDeposit tests the stressing deposit of ether func TestStressEtherDeposit(r *runner.E2ERunner, args []string) { - if len(args) != 2 { - panic("TestStressEtherDeposit requires exactly two arguments: the deposit amount and the number of deposits.") - } + require.Len(r, args, 2) depositAmount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid deposit amount specified for TestMultipleERC20Deposit.") - } + require.True(r, ok) - numDeposits, err := strconv.Atoi(args[1]) - if err != nil || numDeposits < 1 { - panic("Invalid number of deposits specified for TestStressEtherDeposit.") - } + numDeposits := parseInt(r, args[1]) r.Logger.Print("starting stress test of %d deposits", numDeposits) @@ -41,15 +34,10 @@ func TestStressEtherDeposit(r *runner.E2ERunner, args []string) { hash := r.DepositEtherWithAmount(false, depositAmount) r.Logger.Print("index %d: starting deposit, tx hash: %s", i, hash.Hex()) - eg.Go(func() error { - return monitorEtherDeposit(r, hash, i, time.Now()) - }) + eg.Go(func() error { return monitorEtherDeposit(r, hash, i, time.Now()) }) } - // wait for all the deposits to complete - if err := eg.Wait(); err != nil { - panic(err) - } + require.NoError(r, eg.Wait()) r.Logger.Print("all deposits completed") } diff --git a/e2e/e2etests/test_stress_eth_withdraw.go b/e2e/e2etests/test_stress_eth_withdraw.go index 7f73e863a0..3a67ca8f94 100644 --- a/e2e/e2etests/test_stress_eth_withdraw.go +++ b/e2e/e2etests/test_stress_eth_withdraw.go @@ -7,6 +7,7 @@ import ( "time" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/zeta-chain/zetacore/e2e/runner" @@ -16,26 +17,18 @@ import ( // TestStressEtherWithdraw tests the stressing withdraw of ether func TestStressEtherWithdraw(r *runner.E2ERunner, args []string) { - if len(args) != 2 { - panic( - "TestStressEtherWithdraw requires exactly two arguments: the withdrawal amount and the number of withdrawals.", - ) - } + require.Len(r, args, 2) withdrawalAmount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid withdrawal amount specified for TestStressEtherWithdraw.") - } + require.True(r, ok, "Invalid withdrawal amount specified for TestStressEtherWithdraw.") numWithdraws, err := strconv.Atoi(args[1]) - if err != nil || numWithdraws < 1 { - panic("Invalid number of withdrawals specified for TestStressEtherWithdraw.") - } + require.NoError(r, err) + require.GreaterOrEqual(r, numWithdraws, 1) tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, r.ETHZRC20Addr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.WaitForTxReceiptOnZEVM(tx) r.Logger.Print("starting stress test of %d withdraws", numWithdraws) @@ -46,15 +39,13 @@ func TestStressEtherWithdraw(r *runner.E2ERunner, args []string) { // send the withdraws for i := 0; i < numWithdraws; i++ { i := i + tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), withdrawalAmount) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status == 0 { - //r.Logger.Info("index %d: withdraw evm tx failed", index) - panic(fmt.Sprintf("index %d: withdraw evm tx %s failed", i, tx.Hash().Hex())) - } + utils.RequireTxSuccessful(r, receipt) + r.Logger.Print("index %d: starting withdraw, tx hash: %s", i, tx.Hash().Hex()) eg.Go(func() error { @@ -62,10 +53,7 @@ func TestStressEtherWithdraw(r *runner.E2ERunner, args []string) { }) } - // wait for all the withdraws to complete - if err := eg.Wait(); err != nil { - panic(err) - } + require.NoError(r, eg.Wait()) r.Logger.Print("all withdraws completed") } diff --git a/e2e/e2etests/test_update_bytecode_connector.go b/e2e/e2etests/test_update_bytecode_connector.go index 6b88e14972..73786f2971 100644 --- a/e2e/e2etests/test_update_bytecode_connector.go +++ b/e2e/e2etests/test_update_bytecode_connector.go @@ -1,10 +1,10 @@ package e2etests import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testconnectorzevm" "github.com/zeta-chain/zetacore/e2e/runner" @@ -18,17 +18,12 @@ func TestUpdateBytecodeConnector(r *runner.E2ERunner, _ []string) { // Can withdraw 10ZETA amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10)) r.DepositAndApproveWZeta(amount) + tx := r.WithdrawZeta(amount, true) cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) + r.Logger.CCTX(*cctx, "zeta withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Errorf( - "expected cctx status to be %s; got %s, message %s", - crosschaintypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } // Deploy the test contract newTestConnectorAddr, tx, _, err := testconnectorzevm.DeployTestZetaConnectorZEVM( @@ -36,23 +31,17 @@ func TestUpdateBytecodeConnector(r *runner.E2ERunner, _ []string) { r.ZEVMClient, r.WZetaAddr, ) - if err != nil { - panic(err) - } + require.NoError(r, err) // Wait for the contract to be deployed receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("contract deployment failed") - } + utils.RequireTxSuccessful(r, receipt) // Get the code hash of the new contract codeHashRes, err := r.FungibleClient.CodeHash(r.Ctx, &fungibletypes.QueryCodeHashRequest{ Address: newTestConnectorAddr.String(), }) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("New contract code hash: %s", codeHashRes.CodeHash) r.Logger.Info("Updating the bytecode of the Connector") @@ -62,37 +51,21 @@ func TestUpdateBytecodeConnector(r *runner.E2ERunner, _ []string) { codeHashRes.CodeHash, ) res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Update connector bytecode tx hash: %s", res.TxHash) r.Logger.Info("Can interact with the new code of the contract") testConnectorContract, err := testconnectorzevm.NewTestZetaConnectorZEVM(r.ConnectorZEVMAddr, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) response, err := testConnectorContract.Foo(&bind.CallOpts{}) - if err != nil { - panic(err) - } - - if response != "foo" { - panic("unexpected response") - } + require.NoError(r, err) + require.Equal(r, "foo", response) // Can continue to interact with the connector: withdraw 10ZETA r.DepositAndApproveWZeta(amount) tx = r.WithdrawZeta(amount, true) cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "zeta withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Errorf( - "expected cctx status to be %s; got %s, message %s", - crosschaintypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) } diff --git a/e2e/e2etests/test_update_bytecode_zrc20.go b/e2e/e2etests/test_update_bytecode_zrc20.go index 4762ec94bb..ba914655d1 100644 --- a/e2e/e2etests/test_update_bytecode_zrc20.go +++ b/e2e/e2etests/test_update_bytecode_zrc20.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/contracts/testzrc20" "github.com/zeta-chain/zetacore/e2e/runner" @@ -18,13 +19,10 @@ func TestUpdateBytecodeZRC20(r *runner.E2ERunner, _ []string) { // Random approval approved := sample.EthAddress() tx, err := r.ETHZRC20.Approve(r.ZEVMAuth, approved, big.NewInt(1e10)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("approval failed") - } + utils.RequireTxSuccessful(r, receipt) // Deploy the TestZRC20 contract r.Logger.Info("Deploying contract with new bytecode") @@ -35,50 +33,38 @@ func TestUpdateBytecodeZRC20(r *runner.E2ERunner, _ []string) { // #nosec G701 test - always in range uint8(coin.CoinType_Gas), ) - if err != nil { - panic(err) - } + require.NoError(r, err) // Wait for the contract to be deployed receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("contract deployment failed") - } + utils.RequireTxSuccessful(r, receipt) // Get the code hash of the new contract codeHashRes, err := r.FungibleClient.CodeHash(r.Ctx, &fungibletypes.QueryCodeHashRequest{ Address: newZRC20Address.String(), }) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("New contract code hash: %s", codeHashRes.CodeHash) // Get current info of the ZRC20 name, err := r.ETHZRC20.Name(&bind.CallOpts{}) - if err != nil { - panic(err) - } + require.NoError(r, err) + symbol, err := r.ETHZRC20.Symbol(&bind.CallOpts{}) - if err != nil { - panic(err) - } + require.NoError(r, err) + decimals, err := r.ETHZRC20.Decimals(&bind.CallOpts{}) - if err != nil { - panic(err) - } + require.NoError(r, err) + totalSupply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) - if err != nil { - panic(err) - } + require.NoError(r, err) + balance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + approval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) - if err != nil { - panic(err) - } + require.NoError(r, err) r.Logger.Info("Updating the bytecode of the ZRC20") msg := fungibletypes.NewMsgUpdateContractBytecode( @@ -87,116 +73,75 @@ func TestUpdateBytecodeZRC20(r *runner.E2ERunner, _ []string) { codeHashRes.CodeHash, ) res, err := r.ZetaTxServer.BroadcastTx(utils.FungibleAdminName, msg) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("Update zrc20 bytecode tx hash: %s", res.TxHash) // Get new info of the ZRC20 r.Logger.Info("Checking the state of the ZRC20 remains the same") newName, err := r.ETHZRC20.Name(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if name != newName { - panic("name shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, name, newName) + newSymbol, err := r.ETHZRC20.Symbol(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if symbol != newSymbol { - panic("symbol shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, symbol, newSymbol) + newDecimals, err := r.ETHZRC20.Decimals(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if decimals != newDecimals { - panic("decimals shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, decimals, newDecimals) + newTotalSupply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if totalSupply.Cmp(newTotalSupply) != 0 { - panic("total supply shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, 0, totalSupply.Cmp(newTotalSupply)) + newBalance, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } - if balance.Cmp(newBalance) != 0 { - panic("balance shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, 0, balance.Cmp(newBalance)) + newApproval, err := r.ETHZRC20.Allowance(&bind.CallOpts{}, r.DeployerAddress, approved) - if err != nil { - panic(err) - } - if approval.Cmp(newApproval) != 0 { - panic("approval shouldn't change upon bytecode update") - } + require.NoError(r, err) + require.Equal(r, 0, approval.Cmp(newApproval)) r.Logger.Info("Can interact with the new code of the contract") + testZRC20Contract, err := testzrc20.NewTestZRC20(r.ETHZRC20Addr, r.ZEVMClient) - if err != nil { - panic(err) - } + require.NoError(r, err) + tx, err = testZRC20Contract.UpdateNewField(r.ZEVMAuth, big.NewInt(1e10)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("update new field failed") - } + utils.RequireTxSuccessful(r, receipt) + newField, err := testZRC20Contract.NewField(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if newField.Cmp(big.NewInt(1e10)) != 0 { - panic("new field value mismatch") - } + require.NoError(r, err) + require.Equal(r, 0, newField.Cmp(big.NewInt(1e10))) r.Logger.Info("Interacting with the bytecode contract doesn't disrupt the zrc20 contract") tx, err = newZRC20Contract.UpdateNewField(r.ZEVMAuth, big.NewInt(1e5)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("update new field failed") - } + utils.RequireTxSuccessful(r, receipt) + newField, err = newZRC20Contract.NewField(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if newField.Cmp(big.NewInt(1e5)) != 0 { - panic("new field value mismatch on bytecode contract") - } + require.NoError(r, err) + require.Equal(r, 0, newField.Cmp(big.NewInt(1e5)), "new field value mismatch on bytecode contract") + newField, err = testZRC20Contract.NewField(&bind.CallOpts{}) - if err != nil { - panic(err) - } - if newField.Cmp(big.NewInt(1e10)) != 0 { - panic("new field value mismatch on zrc20 contract") - } + require.NoError(r, err) + require.Equal(r, 0, newField.Cmp(big.NewInt(1e10)), "new field value mismatch on zrc20 contract") // can continue to operate the ZRC20 r.Logger.Info("Checking the ZRC20 can continue to operate after state change") tx, err = r.ETHZRC20.Transfer(r.ZEVMAuth, approved, big.NewInt(1e14)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) - if receipt.Status != 1 { - panic("transfer failed") - } + utils.RequireTxSuccessful(r, receipt) + newBalance, err = r.ETHZRC20.BalanceOf(&bind.CallOpts{}, approved) - if err != nil { - panic(err) - } - if newBalance.Cmp(big.NewInt(1e14)) != 0 { - panic("balance not updated") - } + require.NoError(r, err) + require.Equal(r, 0, newBalance.Cmp(big.NewInt(1e14))) } diff --git a/e2e/e2etests/test_zeta_deposit.go b/e2e/e2etests/test_zeta_deposit.go index a6fa98dbcf..056ee5709f 100644 --- a/e2e/e2etests/test_zeta_deposit.go +++ b/e2e/e2etests/test_zeta_deposit.go @@ -3,19 +3,17 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" ) func TestZetaDeposit(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestZetaDeposit requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestZetaDeposit.") - } + require.True(r, ok, "Invalid amount specified for TestZetaDeposit.") hash := r.DepositZetaWithAmount(r.DeployerAddress, amount) diff --git a/e2e/e2etests/test_zeta_deposit_new_address.go b/e2e/e2etests/test_zeta_deposit_new_address.go index c0be712e33..047fbd7042 100644 --- a/e2e/e2etests/test_zeta_deposit_new_address.go +++ b/e2e/e2etests/test_zeta_deposit_new_address.go @@ -3,20 +3,18 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/testutil/sample" ) func TestZetaDepositNewAddress(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestZetaDepositNewAddress requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestZetaDepositNewAddress.") - } + require.True(r, ok) newAddress := sample.EthAddress() hash := r.DepositZetaWithAmount(newAddress, amount) diff --git a/e2e/e2etests/test_zeta_deposit_restricted_address.go b/e2e/e2etests/test_zeta_deposit_restricted_address.go index e6a9d4f23b..d525a97d79 100644 --- a/e2e/e2etests/test_zeta_deposit_restricted_address.go +++ b/e2e/e2etests/test_zeta_deposit_restricted_address.go @@ -4,20 +4,17 @@ import ( "math/big" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/zetaclient/testutils" ) func TestZetaDepositRestricted(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestZetaDepositRestricted requires exactly one argument for the amount.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestZetaDepositRestricted.") - } + require.True(r, ok, "Invalid amount specified for TestZetaDepositRestricted.") // Deposit amount to restricted address r.DepositZetaWithAmount(ethcommon.HexToAddress(testutils.RestrictedEVMAddressTest), amount) diff --git a/e2e/e2etests/test_zeta_withdraw.go b/e2e/e2etests/test_zeta_withdraw.go index b46a403aa2..25b9d3d34a 100644 --- a/e2e/e2etests/test_zeta_withdraw.go +++ b/e2e/e2etests/test_zeta_withdraw.go @@ -1,35 +1,25 @@ package e2etests import ( - "fmt" "math/big" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" ) func TestZetaWithdraw(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestZetaWithdraw requires exactly one argument for the withdrawal.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("invalid amount specified") - } + require.True(r, ok) r.DepositAndApproveWZeta(amount) tx := r.WithdrawZeta(amount, true) cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, tx.Hash().Hex(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "zeta withdraw") - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Errorf( - "expected cctx status to be %s; got %s, message %s", - crosschaintypes.CctxStatus_OutboundMined, - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage, - )) - } + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) } diff --git a/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go b/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go index 151d140a97..ae34058c94 100644 --- a/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go +++ b/e2e/e2etests/test_zeta_withdraw_bitcoin_revert.go @@ -3,6 +3,7 @@ package e2etests import ( "math/big" + "github.com/stretchr/testify/require" connectorzevm "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zetaconnectorzevm.sol" "github.com/zeta-chain/zetacore/e2e/runner" @@ -11,40 +12,31 @@ import ( ) func TestZetaWithdrawBTCRevert(r *runner.E2ERunner, args []string) { - if len(args) != 1 { - panic("TestZetaWithdrawBTCRevert requires exactly one argument for the withdrawal.") - } + require.Len(r, args, 1) amount, ok := big.NewInt(0).SetString(args[0], 10) - if !ok { - panic("Invalid amount specified for TestZetaWithdrawBTCRevert.") - } + require.True(r, ok) r.ZEVMAuth.Value = amount tx, err := r.WZeta.Deposit(r.ZEVMAuth) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.ZEVMAuth.Value = big.NewInt(0) r.Logger.Info("Deposit tx hash: %s", tx.Hash().Hex()) receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.EVMReceipt(*receipt, "Deposit") - if receipt.Status != 1 { - panic("Deposit failed") - } + utils.RequireTxSuccessful(r, receipt) tx, err = r.WZeta.Approve(r.ZEVMAuth, r.ConnectorZEVMAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("wzeta.approve tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + utils.RequireTxSuccessful(r, receipt) + r.Logger.EVMReceipt(*receipt, "Approve") - if receipt.Status != 1 { - panic("Approve failed") - } lessThanAmount := amount.Div(amount, big.NewInt(10)) // 1/10 of amount tx, err = r.ConnectorZEVM.Send(r.ZEVMAuth, connectorzevm.ZetaInterfacesSendInput{ @@ -55,14 +47,12 @@ func TestZetaWithdrawBTCRevert(r *runner.E2ERunner, args []string) { ZetaValueAndGas: lessThanAmount, ZetaParams: nil, }) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("send tx hash: %s", tx.Hash().Hex()) receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + utils.RequiredTxFailed(r, receipt) + r.Logger.EVMReceipt(*receipt, "send") - if receipt.Status != 0 { - panic("Was able to send ZETA to BTC") - } } diff --git a/e2e/e2etests/test_zrc20_swap.go b/e2e/e2etests/test_zrc20_swap.go index 4dfea02cf1..661d2fc40f 100644 --- a/e2e/e2etests/test_zrc20_swap.go +++ b/e2e/e2etests/test_zrc20_swap.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/runner" "github.com/zeta-chain/zetacore/e2e/utils" @@ -24,22 +25,19 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { } zrc20EthPair, err := r.UniswapV2Factory.GetPair(&bind.CallOpts{}, r.ERC20ZRC20Addr, r.ETHZRC20Addr) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("ZRC20-ETH pair receipt pair addr %s", zrc20EthPair.Hex()) tx, err = r.ERC20ZRC20.Approve(r.ZEVMAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("ERC20 ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) tx, err = r.ETHZRC20.Approve(r.ZEVMAuth, r.UniswapV2RouterAddr, big.NewInt(1e18)) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("ETH ZRC20 approval receipt txhash %s status %d", receipt.TxHash, receipt.Status) @@ -61,16 +59,14 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { r.DeployerAddress, big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("Add liquidity receipt txhash %s status %d", receipt.TxHash, receipt.Status) balETHBefore, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + ethOutAmout := big.NewInt(1) tx, err = r.UniswapV2Router.SwapExactTokensForTokens( r.ZEVMAuth, @@ -80,18 +76,14 @@ func TestZRC20Swap(r *runner.E2ERunner, _ []string) { r.DeployerAddress, big.NewInt(time.Now().Add(10*time.Minute).Unix()), ) - if err != nil { - panic(err) - } + require.NoError(r, err) + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) r.Logger.Info("Swap ERC20 ZRC20 for ETH ZRC20 %s status %d", receipt.TxHash, receipt.Status) balETHAfter, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + ethDiff := big.NewInt(0).Sub(balETHAfter, balETHBefore) - if ethDiff.Cmp(ethOutAmout) < 0 { - panic("swap failed") - } + require.NotEqual(r, -1, ethDiff.Cmp(ethOutAmout), "swap failed") } diff --git a/e2e/runner/accounting.go b/e2e/runner/accounting.go index 31a53f9371..4992d46ad8 100644 --- a/e2e/runner/accounting.go +++ b/e2e/runner/accounting.go @@ -19,46 +19,46 @@ type Response struct { Amount Amount `json:"amount"` } -func (runner *E2ERunner) CheckZRC20ReserveAndSupply() error { - runner.Logger.Info("Checking ZRC20 Reserve and Supply") - if err := runner.checkEthTSSBalance(); err != nil { +func (r *E2ERunner) CheckZRC20ReserveAndSupply() error { + r.Logger.Info("Checking ZRC20 Reserve and Supply") + if err := r.checkEthTSSBalance(); err != nil { return err } - if err := runner.checkERC20TSSBalance(); err != nil { + if err := r.checkERC20TSSBalance(); err != nil { return err } - return runner.checkZetaTSSBalance() + return r.checkZetaTSSBalance() } -func (runner *E2ERunner) checkEthTSSBalance() error { - tssBal, err := runner.EVMClient.BalanceAt(runner.Ctx, runner.TSSAddress, nil) +func (r *E2ERunner) checkEthTSSBalance() error { + tssBal, err := r.EVMClient.BalanceAt(r.Ctx, r.TSSAddress, nil) if err != nil { return err } - zrc20Supply, err := runner.ETHZRC20.TotalSupply(&bind.CallOpts{}) + zrc20Supply, err := r.ETHZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } if tssBal.Cmp(zrc20Supply) < 0 { return fmt.Errorf("ETH: TSS balance (%d) < ZRC20 TotalSupply (%d) ", tssBal, zrc20Supply) } - runner.Logger.Info("ETH: TSS balance (%d) >= ZRC20 TotalSupply (%d)", tssBal, zrc20Supply) + r.Logger.Info("ETH: TSS balance (%d) >= ZRC20 TotalSupply (%d)", tssBal, zrc20Supply) return nil } -func (runner *E2ERunner) CheckBtcTSSBalance() error { - utxos, err := runner.BtcRPCClient.ListUnspent() +func (r *E2ERunner) CheckBtcTSSBalance() error { + utxos, err := r.BtcRPCClient.ListUnspent() if err != nil { return err } var btcBalance float64 for _, utxo := range utxos { - if utxo.Address == runner.BTCTSSAddress.EncodeAddress() { + if utxo.Address == r.BTCTSSAddress.EncodeAddress() { btcBalance += utxo.Amount } } - zrc20Supply, err := runner.BTCZRC20.TotalSupply(&bind.CallOpts{}) + zrc20Supply, err := r.BTCZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } @@ -75,7 +75,7 @@ func (runner *E2ERunner) CheckBtcTSSBalance() error { ) } // #nosec G701 test - always in range - runner.Logger.Info( + r.Logger.Info( "BTC: Balance (%d) >= ZRC20 TotalSupply (%d)", int64(btcBalance*1e8), zrc20Supply.Int64()-10000000, @@ -84,24 +84,24 @@ func (runner *E2ERunner) CheckBtcTSSBalance() error { return nil } -func (runner *E2ERunner) checkERC20TSSBalance() error { - erc20Balance, err := runner.ERC20.BalanceOf(&bind.CallOpts{}, runner.ERC20CustodyAddr) +func (r *E2ERunner) checkERC20TSSBalance() error { + erc20Balance, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.ERC20CustodyAddr) if err != nil { return err } - erc20zrc20Supply, err := runner.ERC20ZRC20.TotalSupply(&bind.CallOpts{}) + erc20zrc20Supply, err := r.ERC20ZRC20.TotalSupply(&bind.CallOpts{}) if err != nil { return err } if erc20Balance.Cmp(erc20zrc20Supply) < 0 { return fmt.Errorf("ERC20: TSS balance (%d) < ZRC20 TotalSupply (%d) ", erc20Balance, erc20zrc20Supply) } - runner.Logger.Info("ERC20: TSS balance (%d) >= ERC20 ZRC20 TotalSupply (%d)", erc20Balance, erc20zrc20Supply) + r.Logger.Info("ERC20: TSS balance (%d) >= ERC20 ZRC20 TotalSupply (%d)", erc20Balance, erc20zrc20Supply) return nil } -func (runner *E2ERunner) checkZetaTSSBalance() error { - zetaLocked, err := runner.ConnectorEth.GetLockedAmount(&bind.CallOpts{}) +func (r *E2ERunner) checkZetaTSSBalance() error { + zetaLocked, err := r.ConnectorEth.GetLockedAmount(&bind.CallOpts{}) if err != nil { return err } @@ -121,9 +121,9 @@ func (runner *E2ERunner) checkZetaTSSBalance() error { } zetaSupply, _ := big.NewInt(0).SetString(result.Amount.Amount, 10) if zetaLocked.Cmp(zetaSupply) < 0 { - runner.Logger.Info(fmt.Sprintf("ZETA: TSS balance (%d) < ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply)) + r.Logger.Info(fmt.Sprintf("ZETA: TSS balance (%d) < ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply)) } else { - runner.Logger.Info("ZETA: TSS balance (%d) >= ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply) + r.Logger.Info("ZETA: TSS balance (%d) >= ZRC20 TotalSupply (%d)", zetaLocked, zetaSupply) } return nil } diff --git a/e2e/runner/balances.go b/e2e/runner/balances.go index 3e176bcb8d..8a0c37782a 100644 --- a/e2e/runner/balances.go +++ b/e2e/runner/balances.go @@ -31,39 +31,39 @@ type AccountBalancesDiff struct { } // GetAccountBalances returns the account balances of the accounts used in the E2E test -func (runner *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { +func (r *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) { // zevm - zetaZeta, err := runner.ZEVMClient.BalanceAt(runner.Ctx, runner.DeployerAddress, nil) + zetaZeta, err := r.ZEVMClient.BalanceAt(r.Ctx, r.DeployerAddress, nil) if err != nil { return AccountBalances{}, err } - zetaWZeta, err := runner.WZeta.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + zetaWZeta, err := r.WZeta.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaEth, err := runner.ETHZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + zetaEth, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaErc20, err := runner.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + zetaErc20, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } - zetaBtc, err := runner.BTCZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + zetaBtc, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } // evm - evmEth, err := runner.EVMClient.BalanceAt(runner.Ctx, runner.DeployerAddress, nil) + evmEth, err := r.EVMClient.BalanceAt(r.Ctx, r.DeployerAddress, nil) if err != nil { return AccountBalances{}, err } - evmZeta, err := runner.ZetaEth.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + evmZeta, err := r.ZetaEth.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } - evmErc20, err := runner.ERC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) + evmErc20, err := r.ERC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) if err != nil { return AccountBalances{}, err } @@ -71,7 +71,7 @@ func (runner *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, erro // bitcoin var BtcBTC string if !skipBTC { - if BtcBTC, err = runner.GetBitcoinBalance(); err != nil { + if BtcBTC, err = r.GetBitcoinBalance(); err != nil { return AccountBalances{}, err } } @@ -90,18 +90,18 @@ func (runner *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, erro } // GetBitcoinBalance returns the spendable BTC balance of the BTC address -func (runner *E2ERunner) GetBitcoinBalance() (string, error) { - addr, _, err := runner.GetBtcAddress() +func (r *E2ERunner) GetBitcoinBalance() (string, error) { + addr, _, err := r.GetBtcAddress() if err != nil { return "", fmt.Errorf("failed to get BTC address: %w", err) } - address, err := btcutil.DecodeAddress(addr, runner.BitcoinParams) + address, err := btcutil.DecodeAddress(addr, r.BitcoinParams) if err != nil { return "", fmt.Errorf("failed to decode BTC address: %w", err) } - total, err := runner.GetBitcoinBalanceByAddress(address) + total, err := r.GetBitcoinBalanceByAddress(address) if err != nil { return "", err } @@ -110,8 +110,8 @@ func (runner *E2ERunner) GetBitcoinBalance() (string, error) { } // GetBitcoinBalanceByAddress get btc balance by address. -func (runner *E2ERunner) GetBitcoinBalanceByAddress(address btcutil.Address) (btcutil.Amount, error) { - unspentList, err := runner.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{address}) +func (r *E2ERunner) GetBitcoinBalanceByAddress(address btcutil.Address) (btcutil.Amount, error) { + unspentList, err := r.BtcRPCClient.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{address}) if err != nil { return 0, errors.Wrap(err, "failed to list unspent") } @@ -128,43 +128,43 @@ func (runner *E2ERunner) GetBitcoinBalanceByAddress(address btcutil.Address) (bt // PrintAccountBalances shows the account balances of the accounts used in the E2E test // Note: USDT is mentioned as erc20 here because we want to show the balance of any erc20 contract -func (runner *E2ERunner) PrintAccountBalances(balances AccountBalances) { - runner.Logger.Print(" ---💰 Account info %s ---", runner.DeployerAddress.Hex()) +func (r *E2ERunner) PrintAccountBalances(balances AccountBalances) { + r.Logger.Print(" ---💰 Account info %s ---", r.DeployerAddress.Hex()) // zevm - runner.Logger.Print("ZetaChain:") - runner.Logger.Print("* ZETA balance: %s", balances.ZetaZETA.String()) - runner.Logger.Print("* WZETA balance: %s", balances.ZetaWZETA.String()) - runner.Logger.Print("* ETH balance: %s", balances.ZetaETH.String()) - runner.Logger.Print("* ERC20 balance: %s", balances.ZetaERC20.String()) - runner.Logger.Print("* BTC balance: %s", balances.ZetaBTC.String()) + r.Logger.Print("ZetaChain:") + r.Logger.Print("* ZETA balance: %s", balances.ZetaZETA.String()) + r.Logger.Print("* WZETA balance: %s", balances.ZetaWZETA.String()) + r.Logger.Print("* ETH balance: %s", balances.ZetaETH.String()) + r.Logger.Print("* ERC20 balance: %s", balances.ZetaERC20.String()) + r.Logger.Print("* BTC balance: %s", balances.ZetaBTC.String()) // evm - runner.Logger.Print("EVM:") - runner.Logger.Print("* ZETA balance: %s", balances.EvmZETA.String()) - runner.Logger.Print("* ETH balance: %s", balances.EvmETH.String()) - runner.Logger.Print("* ERC20 balance: %s", balances.EvmERC20.String()) + r.Logger.Print("EVM:") + r.Logger.Print("* ZETA balance: %s", balances.EvmZETA.String()) + r.Logger.Print("* ETH balance: %s", balances.EvmETH.String()) + r.Logger.Print("* ERC20 balance: %s", balances.EvmERC20.String()) // bitcoin - runner.Logger.Print("Bitcoin:") - runner.Logger.Print("* BTC balance: %s", balances.BtcBTC) + r.Logger.Print("Bitcoin:") + r.Logger.Print("* BTC balance: %s", balances.BtcBTC) return } // PrintTotalDiff shows the difference in the account balances of the accounts used in the e2e test from two balances structs -func (runner *E2ERunner) PrintTotalDiff(accoutBalancesDiff AccountBalancesDiff) { - runner.Logger.Print(" ---💰 Total gas spent ---") +func (r *E2ERunner) PrintTotalDiff(accoutBalancesDiff AccountBalancesDiff) { + r.Logger.Print(" ---💰 Total gas spent ---") // show the value only if it is not zero if accoutBalancesDiff.ZETA.Cmp(big.NewInt(0)) != 0 { - runner.Logger.Print("* ZETA spent: %s", accoutBalancesDiff.ZETA.String()) + r.Logger.Print("* ZETA spent: %s", accoutBalancesDiff.ZETA.String()) } if accoutBalancesDiff.ETH.Cmp(big.NewInt(0)) != 0 { - runner.Logger.Print("* ETH spent: %s", accoutBalancesDiff.ETH.String()) + r.Logger.Print("* ETH spent: %s", accoutBalancesDiff.ETH.String()) } if accoutBalancesDiff.ERC20.Cmp(big.NewInt(0)) != 0 { - runner.Logger.Print("* ERC20 spent: %s", accoutBalancesDiff.ERC20.String()) + r.Logger.Print("* ERC20 spent: %s", accoutBalancesDiff.ERC20.String()) } } diff --git a/e2e/runner/bitcoin.go b/e2e/runner/bitcoin.go index d4dc3df15c..c096bfc748 100644 --- a/e2e/runner/bitcoin.go +++ b/e2e/runner/bitcoin.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "fmt" - "math/big" "time" "github.com/btcsuite/btcd/btcjson" @@ -30,29 +29,38 @@ import ( var blockHeaderBTCTimeout = 5 * time.Minute // ListDeployerUTXOs list the deployer's UTXOs -func (runner *E2ERunner) ListDeployerUTXOs() ([]btcjson.ListUnspentResult, error) { +func (r *E2ERunner) ListDeployerUTXOs() ([]btcjson.ListUnspentResult, error) { // query UTXOs from node - utxos, err := runner.BtcRPCClient.ListUnspentMinMaxAddresses( + utxos, err := r.BtcRPCClient.ListUnspentMinMaxAddresses( 1, 9999999, - []btcutil.Address{runner.BTCDeployerAddress}, + []btcutil.Address{r.BTCDeployerAddress}, ) if err != nil { return nil, err } + // filter big-enough UTXOs for test if running on Regtest + if r.IsLocalBitcoin() { + utxosFiltered := []btcjson.ListUnspentResult{} + for _, utxo := range utxos { + if utxo.Amount >= 1.0 { + utxosFiltered = append(utxosFiltered, utxo) + } + } + return utxosFiltered, nil + } + return utxos, nil } // DepositBTCWithAmount deposits BTC on ZetaChain with a specific amount -func (runner *E2ERunner) DepositBTCWithAmount(amount float64) (txHash *chainhash.Hash) { - runner.Logger.Print("⏳ depositing BTC into ZEVM") +func (r *E2ERunner) DepositBTCWithAmount(amount float64) *chainhash.Hash { + r.Logger.Print("⏳ depositing BTC into ZEVM") // list deployer utxos - utxos, err := runner.ListDeployerUTXOs() - if err != nil { - panic(err) - } + utxos, err := r.ListDeployerUTXOs() + require.NoError(r, err) spendableAmount := 0.0 spendableUTXOs := 0 @@ -63,42 +71,33 @@ func (runner *E2ERunner) DepositBTCWithAmount(amount float64) (txHash *chainhash } } - if spendableAmount < amount { - panic(fmt.Errorf( - "not enough spendable BTC to run the test; have %f, require %f", - spendableAmount, - amount, - )) - } + require.LessOrEqual(r, amount, spendableAmount, "not enough spendable BTC to run the test") - runner.Logger.Info("ListUnspent:") - runner.Logger.Info(" spendableAmount: %f", spendableAmount) - runner.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) - runner.Logger.Info("Now sending two txs to TSS address...") + r.Logger.Info("ListUnspent:") + r.Logger.Info(" spendableAmount: %f", spendableAmount) + r.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) + r.Logger.Info("Now sending two txs to TSS address...") - amount = amount + zetabitcoin.DefaultDepositorFee - txHash, err = runner.SendToTSSFromDeployerToDeposit(amount, utxos) - if err != nil { - panic(err) - } - runner.Logger.Info("send BTC to TSS txHash: %s", txHash.String()) + amount += zetabitcoin.DefaultDepositorFee + txHash, err := r.SendToTSSFromDeployerToDeposit(amount, utxos) + require.NoError(r, err) + + r.Logger.Info("send BTC to TSS txHash: %s", txHash.String()) return txHash } // DepositBTC deposits BTC on ZetaChain -func (runner *E2ERunner) DepositBTC(testHeader bool) { - runner.Logger.Print("⏳ depositing BTC into ZEVM") +func (r *E2ERunner) DepositBTC(testHeader bool) { + r.Logger.Print("⏳ depositing BTC into ZEVM") startTime := time.Now() defer func() { - runner.Logger.Print("✅ BTC deposited in %s", time.Since(startTime)) + r.Logger.Print("✅ BTC deposited in %s", time.Since(startTime)) }() // list deployer utxos - utxos, err := runner.ListDeployerUTXOs() - if err != nil { - panic(err) - } + utxos, err := r.ListDeployerUTXOs() + require.NoError(r, err) spendableAmount := 0.0 spendableUTXOs := 0 @@ -109,85 +108,66 @@ func (runner *E2ERunner) DepositBTC(testHeader bool) { } } - if spendableAmount < 1.15 { - panic(fmt.Errorf("not enough spendable BTC to run the test; have %f", spendableAmount)) - } - if spendableUTXOs < 5 { - panic(fmt.Errorf("not enough spendable BTC UTXOs to run the test; have %d", spendableUTXOs)) - } + require.GreaterOrEqual(r, spendableAmount, 1.15, "not enough spendable BTC to run the test") + require.GreaterOrEqual(r, spendableUTXOs, 5, "not enough spendable BTC UTXOs to run the test") - runner.Logger.Info("ListUnspent:") - runner.Logger.Info(" spendableAmount: %f", spendableAmount) - runner.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) - runner.Logger.Info("Now sending two txs to TSS address...") + r.Logger.Info("ListUnspent:") + r.Logger.Info(" spendableAmount: %f", spendableAmount) + r.Logger.Info(" spendableUTXOs: %d", spendableUTXOs) + r.Logger.Info("Now sending two txs to TSS address...") // send two transactions to the TSS address amount1 := 1.1 + zetabitcoin.DefaultDepositorFee - txHash1, err := runner.SendToTSSFromDeployerToDeposit(amount1, utxos[:2]) - if err != nil { - panic(err) - } + txHash1, err := r.SendToTSSFromDeployerToDeposit(amount1, utxos[:2]) + require.NoError(r, err) + amount2 := 0.05 + zetabitcoin.DefaultDepositorFee - txHash2, err := runner.SendToTSSFromDeployerToDeposit(amount2, utxos[2:4]) - if err != nil { - panic(err) - } + txHash2, err := r.SendToTSSFromDeployerToDeposit(amount2, utxos[2:4]) + require.NoError(r, err) // send a donation to the TSS address to compensate for the funds minted automatically during pool creation // and prevent accounting errors - _, err = runner.SendToTSSFromDeployerWithMemo(0.11, utxos[4:5], []byte(constant.DonationMessage)) - if err != nil { - panic(err) - } + _, err = r.SendToTSSFromDeployerWithMemo(0.11, utxos[4:5], []byte(constant.DonationMessage)) + require.NoError(r, err) - runner.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") + r.Logger.Info("testing if the deposit into BTC ZRC20 is successful...") cctx := utils.WaitCctxMinedByInboundHash( - runner.Ctx, + r.Ctx, txHash2.String(), - runner.CctxClient, - runner.Logger, - runner.CctxTimeout, + r.CctxClient, + r.Logger, + r.CctxTimeout, ) - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_OutboundMined { - panic(fmt.Sprintf( - "expected mined status; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined) - balance, err := runner.BTCZRC20.BalanceOf(&bind.CallOpts{}, runner.DeployerAddress) - if err != nil { - panic(err) - } - if balance.Cmp(big.NewInt(0)) != 1 { - panic("balance should be positive") - } + balance, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.DeployerAddress) + require.NoError(r, err) + require.Equal(r, 1, balance.Sign(), "balance should be positive") // due to the high block throughput in localnet, ZetaClient might catch up slowly with the blocks // to optimize block header proof test, this test is directly executed here on the first deposit instead of having a separate test if testHeader { - runner.ProveBTCTransaction(txHash1) + r.ProveBTCTransaction(txHash1) } } -func (runner *E2ERunner) SendToTSSFromDeployerToDeposit(amount float64, inputUTXOs []btcjson.ListUnspentResult) ( +func (r *E2ERunner) SendToTSSFromDeployerToDeposit(amount float64, inputUTXOs []btcjson.ListUnspentResult) ( *chainhash.Hash, error, ) { - return runner.SendToTSSFromDeployerWithMemo(amount, inputUTXOs, runner.DeployerAddress.Bytes()) + return r.SendToTSSFromDeployerWithMemo(amount, inputUTXOs, r.DeployerAddress.Bytes()) } -func (runner *E2ERunner) SendToTSSFromDeployerWithMemo( +func (r *E2ERunner) SendToTSSFromDeployerWithMemo( amount float64, inputUTXOs []btcjson.ListUnspentResult, memo []byte, ) (*chainhash.Hash, error) { - btcRPC := runner.BtcRPCClient - to := runner.BTCTSSAddress - btcDeployerAddress := runner.BTCDeployerAddress - require.NotNil(runner, runner.BTCDeployerAddress, "btcDeployerAddress is nil") + btcRPC := r.BtcRPCClient + to := r.BTCTSSAddress + btcDeployerAddress := r.BTCDeployerAddress + require.NotNil(r, r.BTCDeployerAddress, "btcDeployerAddress is nil") // prepare inputs inputs := make([]btcjson.TransactionInput, len(inputUTXOs)) @@ -218,38 +198,32 @@ func (runner *E2ERunner) SendToTSSFromDeployerWithMemo( } // create raw - runner.Logger.Info("ADDRESS: %s, %s", btcDeployerAddress.EncodeAddress(), to.EncodeAddress()) + r.Logger.Info("ADDRESS: %s, %s", btcDeployerAddress.EncodeAddress(), to.EncodeAddress()) tx, err := btcRPC.CreateRawTransaction(inputs, amountMap, nil) - if err != nil { - panic(err) - } + require.NoError(r, err) // this adds a OP_RETURN + single BYTE len prefix to the data nullData, err := txscript.NullDataScript(memo) - if err != nil { - panic(err) - } - runner.Logger.Info("nulldata (len %d): %x", len(nullData), nullData) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("nulldata (len %d): %x", len(nullData), nullData) + require.NoError(r, err) memoOutput := wire.TxOut{Value: 0, PkScript: nullData} tx.TxOut = append(tx.TxOut, &memoOutput) tx.TxOut[1], tx.TxOut[2] = tx.TxOut[2], tx.TxOut[1] // make sure that TxOut[0] is sent to "to" address; TxOut[2] is change to oneself. TxOut[1] is memo. if !bytes.Equal(tx.TxOut[0].PkScript[2:], to.ScriptAddress()) { - runner.Logger.Info("tx.TxOut[0].PkScript: %x", tx.TxOut[0].PkScript) - runner.Logger.Info("to.ScriptAddress(): %x", to.ScriptAddress()) - runner.Logger.Info("swapping txout[0] with txout[2]") + r.Logger.Info("tx.TxOut[0].PkScript: %x", tx.TxOut[0].PkScript) + r.Logger.Info("to.ScriptAddress(): %x", to.ScriptAddress()) + r.Logger.Info("swapping txout[0] with txout[2]") tx.TxOut[0], tx.TxOut[2] = tx.TxOut[2], tx.TxOut[0] } - runner.Logger.Info("raw transaction: \n") + r.Logger.Info("raw transaction: \n") for idx, txout := range tx.TxOut { - runner.Logger.Info("txout %d", idx) - runner.Logger.Info(" value: %d", txout.Value) - runner.Logger.Info(" PkScript: %x", txout.PkScript) + r.Logger.Info("txout %d", idx) + r.Logger.Info(" value: %d", txout.Value) + r.Logger.Info(" PkScript: %x", txout.PkScript) } inputsForSign := make([]btcjson.RawTxWitnessInput, len(inputs)) @@ -263,75 +237,63 @@ func (runner *E2ERunner) SendToTSSFromDeployerWithMemo( } stx, signed, err := btcRPC.SignRawTransactionWithWallet2(tx, inputsForSign) - require.NoError(runner, err) - require.True(runner, signed, "btc transaction is not signed") + require.NoError(r, err) + require.True(r, signed, "btc transaction is not signed") txid, err := btcRPC.SendRawTransaction(stx, true) - if err != nil { - panic(err) - } - runner.Logger.Info("txid: %+v", txid) - _, err = runner.GenerateToAddressIfLocalBitcoin(6, btcDeployerAddress) - if err != nil { - panic(err) - } + require.NoError(r, err) + r.Logger.Info("txid: %+v", txid) + _, err = r.GenerateToAddressIfLocalBitcoin(6, btcDeployerAddress) + require.NoError(r, err) gtx, err := btcRPC.GetTransaction(txid) - if err != nil { - panic(err) - } - runner.Logger.Info("rawtx confirmation: %d", gtx.BlockIndex) + require.NoError(r, err) + r.Logger.Info("rawtx confirmation: %d", gtx.BlockIndex) rawtx, err := btcRPC.GetRawTransactionVerbose(txid) - if err != nil { - panic(err) - } + require.NoError(r, err) depositorFee := zetabitcoin.DefaultDepositorFee events, err := btcobserver.FilterAndParseIncomingTx( btcRPC, []btcjson.TxRawResult{*rawtx}, 0, - runner.BTCTSSAddress.EncodeAddress(), + r.BTCTSSAddress.EncodeAddress(), log.Logger, - runner.BitcoinParams, + r.BitcoinParams, depositorFee, ) - if err != nil { - panic(err) - } - runner.Logger.Info("bitcoin inbound events:") + require.NoError(r, err) + r.Logger.Info("bitcoin inbound events:") for _, event := range events { - runner.Logger.Info(" TxHash: %s", event.TxHash) - runner.Logger.Info(" From: %s", event.FromAddress) - runner.Logger.Info(" To: %s", event.ToAddress) - runner.Logger.Info(" Amount: %f", event.Value) - runner.Logger.Info(" Memo: %x", event.MemoBytes) + r.Logger.Info(" TxHash: %s", event.TxHash) + r.Logger.Info(" From: %s", event.FromAddress) + r.Logger.Info(" To: %s", event.ToAddress) + r.Logger.Info(" Amount: %f", event.Value) + r.Logger.Info(" Memo: %x", event.MemoBytes) } return txid, nil } // GetBitcoinChainID gets the bitcoin chain ID from the network params -func (runner *E2ERunner) GetBitcoinChainID() int64 { - chainID, err := chains.BitcoinChainIDFromNetworkName(runner.BitcoinParams.Name) - if err != nil { - panic(err) - } +func (r *E2ERunner) GetBitcoinChainID() int64 { + chainID, err := chains.BitcoinChainIDFromNetworkName(r.BitcoinParams.Name) + require.NoError(r, err) return chainID } // IsLocalBitcoin returns true if the runner is running on a local bitcoin network -func (runner *E2ERunner) IsLocalBitcoin() bool { - return runner.BitcoinParams.Name == chains.BitcoinRegnetParams.Name +func (r *E2ERunner) IsLocalBitcoin() bool { + return r.BitcoinParams.Name == chains.BitcoinRegnetParams.Name } // GenerateToAddressIfLocalBitcoin generates blocks to an address if the runner is interacting // with a local bitcoin network -func (runner *E2ERunner) GenerateToAddressIfLocalBitcoin( +func (r *E2ERunner) GenerateToAddressIfLocalBitcoin( numBlocks int64, address btcutil.Address, ) ([]*chainhash.Hash, error) { // if not local bitcoin network, do nothing - if runner.IsLocalBitcoin() { - return runner.BtcRPCClient.GenerateToAddress(numBlocks, address, nil) + if r.IsLocalBitcoin() { + return r.BtcRPCClient.GenerateToAddress(numBlocks, address, nil) } return nil, nil } @@ -339,7 +301,7 @@ func (runner *E2ERunner) GenerateToAddressIfLocalBitcoin( // MineBlocksIfLocalBitcoin mines blocks on the local BTC chain at a rate of 1 blocks every 5 seconds // and returns a channel that can be used to stop the mining // If the chain is not local, the function does nothing -func (runner *E2ERunner) MineBlocksIfLocalBitcoin() func() { +func (r *E2ERunner) MineBlocksIfLocalBitcoin() func() { stopChan := make(chan struct{}) go func() { for { @@ -347,10 +309,9 @@ func (runner *E2ERunner) MineBlocksIfLocalBitcoin() func() { case <-stopChan: return default: - _, err := runner.GenerateToAddressIfLocalBitcoin(1, runner.BTCDeployerAddress) - if err != nil { - panic(err) - } + _, err := r.GenerateToAddressIfLocalBitcoin(1, r.BTCDeployerAddress) + require.NoError(r, err) + time.Sleep(3 * time.Second) } } @@ -362,78 +323,61 @@ func (runner *E2ERunner) MineBlocksIfLocalBitcoin() func() { } // ProveBTCTransaction proves that a BTC transaction is in a block header and that the block header is in ZetaChain -func (runner *E2ERunner) ProveBTCTransaction(txHash *chainhash.Hash) { +func (r *E2ERunner) ProveBTCTransaction(txHash *chainhash.Hash) { // get tx result - btc := runner.BtcRPCClient + btc := r.BtcRPCClient txResult, err := btc.GetTransaction(txHash) - if err != nil { - panic("should get outTx result") - } - if txResult.Confirmations <= 0 { - panic("outTx should have already confirmed") - } + require.NoError(r, err, "should get tx result") + require.True(r, txResult.Confirmations > 0, "tx should have already confirmed") + txBytes, err := hex.DecodeString(txResult.Hex) - if err != nil { - panic(err) - } + require.NoError(r, err) // get the block with verbose transactions blockHash, err := chainhash.NewHashFromStr(txResult.BlockHash) - if err != nil { - panic(err) - } + require.NoError(r, err) + blockVerbose, err := btc.GetBlockVerboseTx(blockHash) - if err != nil { - panic("should get block verbose tx") - } + require.NoError(r, err, "should get block verbose tx") // get the block header header, err := btc.GetBlockHeader(blockHash) - if err != nil { - panic("should get block header") - } + require.NoError(r, err, "should get block header") // collect all the txs in the block txns := []*btcutil.Tx{} for _, res := range blockVerbose.Tx { txBytes, err := hex.DecodeString(res.Hex) - if err != nil { - panic(err) - } + require.NoError(r, err) + tx, err := btcutil.NewTxFromBytes(txBytes) - if err != nil { - panic(err) - } + require.NoError(r, err) + txns = append(txns, tx) } // build merkle proof mk := bitcoin.NewMerkle(txns) path, index, err := mk.BuildMerkleProof(int(txResult.BlockIndex)) - if err != nil { - panic("should build merkle proof") - } + require.NoError(r, err, "should build merkle proof") // verify merkle proof statically pass := bitcoin.Prove(*txHash, header.MerkleRoot, path, index) - if !pass { - panic("should verify merkle proof") - } + require.True(r, pass, "should verify merkle proof") // wait for block header to show up in ZetaChain startTime := time.Now() hash := header.BlockHash() for { // timeout - if time.Since(startTime) > blockHeaderBTCTimeout { - panic("timed out waiting for block header to show up in observer") - } + reachedTimeout := time.Since(startTime) > blockHeaderBTCTimeout + require.False(r, reachedTimeout, "timed out waiting for block header to show up in observer") - _, err := runner.LightclientClient.BlockHeader(runner.Ctx, &lightclienttypes.QueryGetBlockHeaderRequest{ + _, err := r.LightclientClient.BlockHeader(r.Ctx, &lightclienttypes.QueryGetBlockHeaderRequest{ BlockHash: hash.CloneBytes(), }) if err != nil { - runner.Logger.Info( + r.Logger.Info( "waiting for block header to show up in observer... current hash %s; err %s", hash.String(), err.Error(), @@ -446,18 +390,15 @@ func (runner *E2ERunner) ProveBTCTransaction(txHash *chainhash.Hash) { } // verify merkle proof through RPC - res, err := runner.LightclientClient.Prove(runner.Ctx, &lightclienttypes.QueryProveRequest{ + res, err := r.LightclientClient.Prove(r.Ctx, &lightclienttypes.QueryProveRequest{ ChainId: chains.BitcoinRegtest.ChainId, TxHash: txHash.String(), BlockHash: blockHash.String(), Proof: proofs.NewBitcoinProof(txBytes, path, index), TxIndex: 0, // bitcoin doesn't use txIndex }) - if err != nil { - panic(err) - } - if !res.Valid { - panic("txProof should be valid") - } - runner.Logger.Info("OK: txProof verified for inTx: %s", txHash.String()) + require.NoError(r, err) + require.True(r, res.Valid, "txProof should be valid") + + r.Logger.Info("OK: txProof verified for inTx: %s", txHash.String()) } diff --git a/e2e/runner/e2etest.go b/e2e/runner/e2etest.go index c6e49bdc9d..1ee9c34c19 100644 --- a/e2e/runner/e2etest.go +++ b/e2e/runner/e2etest.go @@ -61,7 +61,7 @@ type E2ETestRunConfig struct { } // GetE2ETestsToRunByName prepares a list of E2ETests to run based on given test names without arguments -func (runner *E2ERunner) GetE2ETestsToRunByName(availableTests []E2ETest, testNames ...string) ([]E2ETest, error) { +func (r *E2ERunner) GetE2ETestsToRunByName(availableTests []E2ETest, testNames ...string) ([]E2ETest, error) { tests := []E2ETestRunConfig{} for _, testName := range testNames { tests = append(tests, E2ETestRunConfig{ @@ -69,11 +69,11 @@ func (runner *E2ERunner) GetE2ETestsToRunByName(availableTests []E2ETest, testNa Args: []string{}, }) } - return runner.GetE2ETestsToRunByConfig(availableTests, tests) + return r.GetE2ETestsToRunByConfig(availableTests, tests) } // GetE2ETestsToRunByConfig prepares a list of E2ETests to run based on provided test names and their corresponding arguments -func (runner *E2ERunner) GetE2ETestsToRunByConfig( +func (r *E2ERunner) GetE2ETestsToRunByConfig( availableTests []E2ETest, testConfigs []E2ETestRunConfig, ) ([]E2ETest, error) { diff --git a/e2e/runner/evm.go b/e2e/runner/evm.go index 355b692ec5..523e01e207 100644 --- a/e2e/runner/evm.go +++ b/e2e/runner/evm.go @@ -9,6 +9,7 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/e2e/utils" "github.com/zeta-chain/zetacore/pkg/chains" @@ -20,169 +21,146 @@ import ( var blockHeaderETHTimeout = 5 * time.Minute // WaitForTxReceiptOnEvm waits for a tx receipt on EVM -func (runner *E2ERunner) WaitForTxReceiptOnEvm(tx *ethtypes.Transaction) { - defer func() { - runner.Unlock() - }() - runner.Lock() +func (r *E2ERunner) WaitForTxReceiptOnEvm(tx *ethtypes.Transaction) { + r.Lock() + defer r.Unlock() - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) } // MintERC20OnEvm mints ERC20 on EVM // amount is a multiple of 1e18 -func (runner *E2ERunner) MintERC20OnEvm(amountERC20 int64) { - defer func() { - runner.Unlock() - }() - runner.Lock() +func (r *E2ERunner) MintERC20OnEvm(amountERC20 int64) { + r.Lock() + defer r.Unlock() amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountERC20)) - tx, err := runner.ERC20.Mint(runner.EVMAuth, amount) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("mint failed") - } - runner.Logger.Info("Mint receipt tx hash: %s", tx.Hash().Hex()) + tx, err := r.ERC20.Mint(r.EVMAuth, amount) + require.NoError(r, err) + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) + + r.Logger.Info("Mint receipt tx hash: %s", tx.Hash().Hex()) } // SendERC20OnEvm sends ERC20 to an address on EVM // this allows the ERC20 contract deployer to funds other accounts on EVM // amountERC20 is a multiple of 1e18 -func (runner *E2ERunner) SendERC20OnEvm(address ethcommon.Address, amountERC20 int64) *ethtypes.Transaction { +func (r *E2ERunner) SendERC20OnEvm(address ethcommon.Address, amountERC20 int64) *ethtypes.Transaction { // the deployer might be sending ERC20 in different goroutines - defer func() { - runner.Unlock() - }() - runner.Lock() + r.Lock() + defer r.Unlock() amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(amountERC20)) // transfer - tx, err := runner.ERC20.Transfer(runner.EVMAuth, address, amount) - if err != nil { - panic(err) - } + tx, err := r.ERC20.Transfer(r.EVMAuth, address, amount) + require.NoError(r, err) + return tx } -func (runner *E2ERunner) DepositERC20() ethcommon.Hash { - runner.Logger.Print("⏳ depositing ERC20 into ZEVM") +func (r *E2ERunner) DepositERC20() ethcommon.Hash { + r.Logger.Print("⏳ depositing ERC20 into ZEVM") - return runner.DepositERC20WithAmountAndMessage(runner.DeployerAddress, big.NewInt(1e18), []byte{}) + return r.DepositERC20WithAmountAndMessage(r.DeployerAddress, big.NewInt(1e18), []byte{}) } -func (runner *E2ERunner) DepositERC20WithAmountAndMessage( - to ethcommon.Address, - amount *big.Int, - msg []byte, -) ethcommon.Hash { +func (r *E2ERunner) DepositERC20WithAmountAndMessage(to ethcommon.Address, amount *big.Int, msg []byte) ethcommon.Hash { // reset allowance, necessary for USDT - tx, err := runner.ERC20.Approve(runner.EVMAuth, runner.ERC20CustodyAddr, big.NewInt(0)) - if err != nil { - panic(err) - } - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - runner.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) + tx, err := r.ERC20.Approve(r.EVMAuth, r.ERC20CustodyAddr, big.NewInt(0)) + require.NoError(r, err) - tx, err = runner.ERC20.Approve(runner.EVMAuth, runner.ERC20CustodyAddr, amount) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("approve failed") - } - runner.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) - tx, err = runner.ERC20Custody.Deposit(runner.EVMAuth, to.Bytes(), runner.ERC20Addr, amount, msg) - runner.Logger.Info("TX: %v", tx) + r.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) - if err != nil { - panic(err) - } - receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit failed") - } - runner.Logger.Info("Deposit receipt tx hash: %s, status %d", receipt.TxHash.Hex(), receipt.Status) + tx, err = r.ERC20.Approve(r.EVMAuth, r.ERC20CustodyAddr, amount) + require.NoError(r, err) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) + + r.Logger.Info("ERC20 Approve receipt tx hash: %s", tx.Hash().Hex()) + + tx, err = r.ERC20Custody.Deposit(r.EVMAuth, to.Bytes(), r.ERC20Addr, amount, msg) + require.NoError(r, err) + + r.Logger.Info("TX: %v", tx) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) + + r.Logger.Info("Deposit receipt tx hash: %s, status %d", receipt.TxHash.Hex(), receipt.Status) for _, log := range receipt.Logs { - event, err := runner.ERC20Custody.ParseDeposited(*log) + event, err := r.ERC20Custody.ParseDeposited(*log) if err != nil { continue } - runner.Logger.Info("Deposited event:") - runner.Logger.Info(" Recipient address: %x", event.Recipient) - runner.Logger.Info(" ERC20 address: %s", event.Asset.Hex()) - runner.Logger.Info(" Amount: %d", event.Amount) - runner.Logger.Info(" Message: %x", event.Message) + r.Logger.Info("Deposited event:") + r.Logger.Info(" Recipient address: %x", event.Recipient) + r.Logger.Info(" ERC20 address: %s", event.Asset.Hex()) + r.Logger.Info(" Amount: %d", event.Amount) + r.Logger.Info(" Message: %x", event.Message) } return tx.Hash() } // DepositEther sends Ethers into ZEVM -func (runner *E2ERunner) DepositEther(testHeader bool) ethcommon.Hash { +func (r *E2ERunner) DepositEther(testHeader bool) ethcommon.Hash { amount := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(100)) // 100 eth - return runner.DepositEtherWithAmount(testHeader, amount) + return r.DepositEtherWithAmount(testHeader, amount) } // DepositEtherWithAmount sends Ethers into ZEVM -func (runner *E2ERunner) DepositEtherWithAmount(testHeader bool, amount *big.Int) ethcommon.Hash { - runner.Logger.Print("⏳ depositing Ethers into ZEVM") +func (r *E2ERunner) DepositEtherWithAmount(testHeader bool, amount *big.Int) ethcommon.Hash { + r.Logger.Print("⏳ depositing Ethers into ZEVM") - signedTx, err := runner.SendEther(runner.TSSAddress, amount, nil) - if err != nil { - panic(err) - } - runner.Logger.EVMTransaction(*signedTx, "send to TSS") + signedTx, err := r.SendEther(r.TSSAddress, amount, nil) + require.NoError(r, err) - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, signedTx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("deposit failed") - } - runner.Logger.EVMReceipt(*receipt, "send to TSS") + r.Logger.EVMTransaction(*signedTx, "send to TSS") + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, signedTx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt, "deposit failed") + + r.Logger.EVMReceipt(*receipt, "send to TSS") // due to the high block throughput in localnet, ZetaClient might catch up slowly with the blocks // to optimize block header proof test, this test is directly executed here on the first deposit instead of having a separate test if testHeader { - runner.ProveEthTransaction(receipt) + r.ProveEthTransaction(receipt) } return signedTx.Hash() } // SendEther sends ethers to the TSS on EVM -func (runner *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { - evmClient := runner.EVMClient +func (r *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { + evmClient := r.EVMClient - nonce, err := evmClient.PendingNonceAt(runner.Ctx, runner.DeployerAddress) + nonce, err := evmClient.PendingNonceAt(r.Ctx, r.DeployerAddress) if err != nil { return nil, err } gasLimit := uint64(30000) // in units - gasPrice, err := evmClient.SuggestGasPrice(runner.Ctx) + gasPrice, err := evmClient.SuggestGasPrice(r.Ctx) if err != nil { return nil, err } - tx := ethtypes.NewTransaction(nonce, runner.TSSAddress, value, gasLimit, gasPrice, data) - chainID, err := evmClient.ChainID(runner.Ctx) + tx := ethtypes.NewTransaction(nonce, r.TSSAddress, value, gasLimit, gasPrice, data) + chainID, err := evmClient.ChainID(r.Ctx) if err != nil { return nil, err } - deployerPrivkey, err := crypto.HexToECDSA(runner.DeployerPrivateKey) + deployerPrivkey, err := crypto.HexToECDSA(r.DeployerPrivateKey) if err != nil { return nil, err } @@ -191,7 +169,7 @@ func (runner *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []b if err != nil { return nil, err } - err = evmClient.SendTransaction(runner.Ctx, signedTx) + err = evmClient.SendTransaction(r.Ctx, signedTx) if err != nil { return nil, err } @@ -200,7 +178,7 @@ func (runner *E2ERunner) SendEther(_ ethcommon.Address, value *big.Int, data []b } // ProveEthTransaction proves an ETH transaction on ZetaChain -func (runner *E2ERunner) ProveEthTransaction(receipt *ethtypes.Receipt) { +func (r *E2ERunner) ProveEthTransaction(receipt *ethtypes.Receipt) { startTime := time.Now() txHash := receipt.TxHash @@ -209,23 +187,21 @@ func (runner *E2ERunner) ProveEthTransaction(receipt *ethtypes.Receipt) { // #nosec G701 test - always in range txIndex := int(receipt.TransactionIndex) - block, err := runner.EVMClient.BlockByHash(runner.Ctx, blockHash) - if err != nil { - panic(err) - } + block, err := r.EVMClient.BlockByHash(r.Ctx, blockHash) + require.NoError(r, err) + for { // check timeout - if time.Since(startTime) > blockHeaderETHTimeout { - panic("timeout waiting for block header") - } + reachedTimeout := time.Since(startTime) > blockHeaderETHTimeout + require.False(r, reachedTimeout, "timeout waiting for block header") - _, err := runner.LightclientClient.BlockHeader(runner.Ctx, &lightclienttypes.QueryGetBlockHeaderRequest{ + _, err := r.LightclientClient.BlockHeader(r.Ctx, &lightclienttypes.QueryGetBlockHeaderRequest{ BlockHash: blockHash.Bytes(), }) if err != nil { - runner.Logger.Info("WARN: block header not found; retrying... error: %s", err.Error()) + r.Logger.Info("WARN: block header not found; retrying... error: %s", err.Error()) } else { - runner.Logger.Info("OK: block header found") + r.Logger.Info("OK: block header found") break } @@ -233,42 +209,36 @@ func (runner *E2ERunner) ProveEthTransaction(receipt *ethtypes.Receipt) { } trie := ethereum.NewTrie(block.Transactions()) - if trie.Hash() != block.Header().TxHash { - panic("tx root hash & block tx root mismatch") - } + require.Equal(r, trie.Hash(), block.Header().TxHash, "tx root hash & block tx root mismatch") + txProof, err := trie.GenerateProof(txIndex) - if err != nil { - panic("error generating txProof") - } + require.NoError(r, err, "error generating txProof") + val, err := txProof.Verify(block.TxHash(), txIndex) - if err != nil { - panic("error verifying txProof") - } + require.NoError(r, err, "error verifying txProof") + var txx ethtypes.Transaction - err = txx.UnmarshalBinary(val) - if err != nil { - panic("error unmarshalling txProof'd tx") - } - res, err := runner.LightclientClient.Prove(runner.Ctx, &lightclienttypes.QueryProveRequest{ + require.NoError(r, txx.UnmarshalBinary(val)) + + res, err := r.LightclientClient.Prove(r.Ctx, &lightclienttypes.QueryProveRequest{ BlockHash: blockHash.Hex(), TxIndex: int64(txIndex), TxHash: txHash.Hex(), Proof: proofs.NewEthereumProof(txProof), ChainId: chains.GoerliLocalnet.ChainId, }) - if err != nil { - panic(err) - } - if !res.Valid { - panic("txProof invalid") // FIXME: don't do this in production - } - runner.Logger.Info("OK: txProof verified") + + // FIXME: @lumtis: don't do this in production + require.NoError(r, err) + require.True(r, res.Valid, "txProof invalid") + + r.Logger.Info("OK: txProof verified") } // AnvilMineBlocks mines blocks on Anvil localnet // the block time is provided in seconds // the method returns a function to stop the mining -func (runner *E2ERunner) AnvilMineBlocks(url string, blockTime int) (func(), error) { +func (r *E2ERunner) AnvilMineBlocks(url string, blockTime int) (func(), error) { stop := make(chan struct{}) client, err := rpc.Dial(url) @@ -286,7 +256,7 @@ func (runner *E2ERunner) AnvilMineBlocks(url string, blockTime int) (func(), err time.Sleep(time.Duration(blockTime) * time.Second) var result interface{} - err = client.CallContext(runner.Ctx, &result, "evm_mine") + err = client.CallContext(r.Ctx, &result, "evm_mine") if err != nil { log.Fatalf("Failed to mine a new block: %v", err) } diff --git a/e2e/runner/report.go b/e2e/runner/report.go index a25360a109..d80024e0dd 100644 --- a/e2e/runner/report.go +++ b/e2e/runner/report.go @@ -53,13 +53,13 @@ func (tr TestReports) String(prefix string) (string, error) { } // PrintTestReports prints the test reports -func (runner *E2ERunner) PrintTestReports(tr TestReports) { - runner.Logger.Print(" ---📈 E2E Test Report ---") +func (r *E2ERunner) PrintTestReports(tr TestReports) { + r.Logger.Print(" ---📈 E2E Test Report ---") table, err := tr.String("") if err != nil { - runner.Logger.Print("Error rendering test report: %s", err) + r.Logger.Print("Error rendering test report: %s", err) } - runner.Logger.PrintNoPrefix(table) + r.Logger.PrintNoPrefix(table) } // NetworkReport is a struct that contains the report for the network used after running e2e tests @@ -87,9 +87,9 @@ func (nr NetworkReport) Validate() error { } // GenerateNetworkReport generates a report for the network used after running e2e tests -func (runner *E2ERunner) GenerateNetworkReport() (NetworkReport, error) { +func (r *E2ERunner) GenerateNetworkReport() (NetworkReport, error) { // get the emissions pool balance - balanceRes, err := runner.BankClient.Balance(runner.Ctx, &banktypes.QueryBalanceRequest{ + balanceRes, err := r.BankClient.Balance(r.Ctx, &banktypes.QueryBalanceRequest{ Address: txserver.EmissionsPoolAddress, Denom: config.BaseDenom, }) @@ -101,13 +101,13 @@ func (runner *E2ERunner) GenerateNetworkReport() (NetworkReport, error) { // fetch the height and number of cctxs, this gives a better idea on the activity of the network // get the block height - blockRes, err := runner.ZEVMClient.BlockNumber(runner.Ctx) + blockRes, err := r.ZEVMClient.BlockNumber(r.Ctx) if err != nil { return NetworkReport{}, err } // get the number of cctxs - cctxsRes, err := runner.CctxClient.CctxAll(runner.Ctx, &crosschaintypes.QueryAllCctxRequest{}) + cctxsRes, err := r.CctxClient.CctxAll(r.Ctx, &crosschaintypes.QueryAllCctxRequest{}) if err != nil { return NetworkReport{}, err } @@ -121,10 +121,9 @@ func (runner *E2ERunner) GenerateNetworkReport() (NetworkReport, error) { } // PrintNetworkReport prints the network report -func (runner *E2ERunner) PrintNetworkReport(nr NetworkReport) { - runner.Logger.Print(" ---📈 Network Report ---") - runner.Logger.Print("Block Height: %d", nr.Height) - runner.Logger.Print("CCTX Processed: %d", nr.CctxCount) - runner.Logger.Print("Emissions Pool Balance: %sZETA", nr.EmissionsPoolBalance.Quo(sdkmath.NewIntFromUint64(1e18))) - +func (r *E2ERunner) PrintNetworkReport(nr NetworkReport) { + r.Logger.Print(" ---📈 Network Report ---") + r.Logger.Print("Block Height: %d", nr.Height) + r.Logger.Print("CCTX Processed: %d", nr.CctxCount) + r.Logger.Print("Emissions Pool Balance: %sZETA", nr.EmissionsPoolBalance.Quo(sdkmath.NewIntFromUint64(1e18))) } diff --git a/e2e/runner/run.go b/e2e/runner/run.go index f24ff9d9f8..c05129b775 100644 --- a/e2e/runner/run.go +++ b/e2e/runner/run.go @@ -1,15 +1,13 @@ package runner import ( - "fmt" - "runtime" "time" ) // RunE2ETests runs a list of e2e tests -func (runner *E2ERunner) RunE2ETests(e2eTests []E2ETest) (err error) { +func (r *E2ERunner) RunE2ETests(e2eTests []E2ETest) (err error) { for _, e2eTest := range e2eTests { - if err := runner.RunE2ETest(e2eTest, true); err != nil { + if err := r.RunE2ETest(e2eTest, true); err != nil { return err } } @@ -17,64 +15,53 @@ func (runner *E2ERunner) RunE2ETests(e2eTests []E2ETest) (err error) { } // RunE2ETest runs a e2e test -func (runner *E2ERunner) RunE2ETest(e2eTest E2ETest, checkAccounting bool) (err error) { - // return an error on panic - // https://github.com/zeta-chain/node/issues/1500 - defer func() { - if r := recover(); r != nil { - // print stack trace - stack := make([]byte, 4096) - n := runtime.Stack(stack, false) - err = fmt.Errorf("%s failed: %v, stack trace %s", e2eTest.Name, r, stack[:n]) - } - }() - +func (r *E2ERunner) RunE2ETest(e2eTest E2ETest, checkAccounting bool) error { startTime := time.Now() - runner.Logger.Print("⏳running - %s", e2eTest.Description) + r.Logger.Print("⏳running - %s", e2eTest.Description) // run e2e test, if args are not provided, use default args args := e2eTest.Args if len(args) == 0 { args = e2eTest.DefaultArgs() } - e2eTest.E2ETest(runner, args) + e2eTest.E2ETest(r, args) //check supplies if checkAccounting { - if err := runner.CheckZRC20ReserveAndSupply(); err != nil { + if err := r.CheckZRC20ReserveAndSupply(); err != nil { return err } } - runner.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTest.Description) + r.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTest.Description) - return err + return nil } // RunE2ETestsIntoReport runs a list of e2e tests by name in a list of e2e tests and returns a report // The function doesn't return an error, it returns a report with the error -func (runner *E2ERunner) RunE2ETestsIntoReport(e2eTests []E2ETest) (TestReports, error) { +func (r *E2ERunner) RunE2ETestsIntoReport(e2eTests []E2ETest) (TestReports, error) { // go through all tests reports := make(TestReports, 0, len(e2eTests)) for _, test := range e2eTests { // get info before test - balancesBefore, err := runner.GetAccountBalances(true) + balancesBefore, err := r.GetAccountBalances(true) if err != nil { return nil, err } timeBefore := time.Now() // run test - testErr := runner.RunE2ETest(test, false) + testErr := r.RunE2ETest(test, false) if testErr != nil { - runner.Logger.Print("test %s failed: %s", test.Name, testErr.Error()) + r.Logger.Print("test %s failed: %s", test.Name, testErr.Error()) } // wait 5 sec to make sure we get updated balances time.Sleep(5 * time.Second) // get info after test - balancesAfter, err := runner.GetAccountBalances(true) + balancesAfter, err := r.GetAccountBalances(true) if err != nil { return nil, err } diff --git a/e2e/runner/runner.go b/e2e/runner/runner.go index 2f2f0e49cc..e27de63247 100644 --- a/e2e/runner/runner.go +++ b/e2e/runner/runner.go @@ -13,6 +13,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" @@ -28,6 +29,7 @@ import ( "github.com/zeta-chain/zetacore/e2e/contracts/erc20" "github.com/zeta-chain/zetacore/e2e/contracts/zevmswap" "github.com/zeta-chain/zetacore/e2e/txserver" + "github.com/zeta-chain/zetacore/e2e/utils" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" @@ -144,7 +146,6 @@ func NewE2ERunner( ) *E2ERunner { r := &E2ERunner{ Name: name, - Ctx: ctx, CtxCancel: ctxCancel, DeployerAddress: deployerAddress, @@ -165,91 +166,95 @@ func NewE2ERunner( Logger: logger, } + + r.Ctx = utils.WithTesting(ctx, r) + for _, opt := range opts { opt(r) } + return r } // CopyAddressesFrom copies addresses from another E2ETestRunner that initialized the contracts -func (runner *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) { +func (r *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) { // copy TSS address - runner.TSSAddress = other.TSSAddress - runner.BTCTSSAddress = other.BTCTSSAddress + r.TSSAddress = other.TSSAddress + r.BTCTSSAddress = other.BTCTSSAddress // copy addresses - runner.ZetaEthAddr = other.ZetaEthAddr - runner.ConnectorEthAddr = other.ConnectorEthAddr - runner.ERC20CustodyAddr = other.ERC20CustodyAddr - runner.ERC20Addr = other.ERC20Addr - runner.ERC20ZRC20Addr = other.ERC20ZRC20Addr - runner.ETHZRC20Addr = other.ETHZRC20Addr - runner.BTCZRC20Addr = other.BTCZRC20Addr - runner.UniswapV2FactoryAddr = other.UniswapV2FactoryAddr - runner.UniswapV2RouterAddr = other.UniswapV2RouterAddr - runner.ConnectorZEVMAddr = other.ConnectorZEVMAddr - runner.WZetaAddr = other.WZetaAddr - runner.EvmTestDAppAddr = other.EvmTestDAppAddr - runner.ZEVMSwapAppAddr = other.ZEVMSwapAppAddr - runner.ContextAppAddr = other.ContextAppAddr - runner.SystemContractAddr = other.SystemContractAddr - runner.ZevmTestDAppAddr = other.ZevmTestDAppAddr + r.ZetaEthAddr = other.ZetaEthAddr + r.ConnectorEthAddr = other.ConnectorEthAddr + r.ERC20CustodyAddr = other.ERC20CustodyAddr + r.ERC20Addr = other.ERC20Addr + r.ERC20ZRC20Addr = other.ERC20ZRC20Addr + r.ETHZRC20Addr = other.ETHZRC20Addr + r.BTCZRC20Addr = other.BTCZRC20Addr + r.UniswapV2FactoryAddr = other.UniswapV2FactoryAddr + r.UniswapV2RouterAddr = other.UniswapV2RouterAddr + r.ConnectorZEVMAddr = other.ConnectorZEVMAddr + r.WZetaAddr = other.WZetaAddr + r.EvmTestDAppAddr = other.EvmTestDAppAddr + r.ZEVMSwapAppAddr = other.ZEVMSwapAppAddr + r.ContextAppAddr = other.ContextAppAddr + r.SystemContractAddr = other.SystemContractAddr + r.ZevmTestDAppAddr = other.ZevmTestDAppAddr // create instances of contracts - runner.ZetaEth, err = zetaeth.NewZetaEth(runner.ZetaEthAddr, runner.EVMClient) + r.ZetaEth, err = zetaeth.NewZetaEth(r.ZetaEthAddr, r.EVMClient) if err != nil { return err } - runner.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(runner.ConnectorEthAddr, runner.EVMClient) + r.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(r.ConnectorEthAddr, r.EVMClient) if err != nil { return err } - runner.ERC20Custody, err = erc20custody.NewERC20Custody(runner.ERC20CustodyAddr, runner.EVMClient) + r.ERC20Custody, err = erc20custody.NewERC20Custody(r.ERC20CustodyAddr, r.EVMClient) if err != nil { return err } - runner.ERC20, err = erc20.NewERC20(runner.ERC20Addr, runner.EVMClient) + r.ERC20, err = erc20.NewERC20(r.ERC20Addr, r.EVMClient) if err != nil { return err } - runner.ERC20ZRC20, err = zrc20.NewZRC20(runner.ERC20ZRC20Addr, runner.ZEVMClient) + r.ERC20ZRC20, err = zrc20.NewZRC20(r.ERC20ZRC20Addr, r.ZEVMClient) if err != nil { return err } - runner.ETHZRC20, err = zrc20.NewZRC20(runner.ETHZRC20Addr, runner.ZEVMClient) + r.ETHZRC20, err = zrc20.NewZRC20(r.ETHZRC20Addr, r.ZEVMClient) if err != nil { return err } - runner.BTCZRC20, err = zrc20.NewZRC20(runner.BTCZRC20Addr, runner.ZEVMClient) + r.BTCZRC20, err = zrc20.NewZRC20(r.BTCZRC20Addr, r.ZEVMClient) if err != nil { return err } - runner.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(runner.UniswapV2FactoryAddr, runner.ZEVMClient) + r.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(r.UniswapV2FactoryAddr, r.ZEVMClient) if err != nil { return err } - runner.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(runner.UniswapV2RouterAddr, runner.ZEVMClient) + r.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(r.UniswapV2RouterAddr, r.ZEVMClient) if err != nil { return err } - runner.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(runner.ConnectorZEVMAddr, runner.ZEVMClient) + r.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(r.ConnectorZEVMAddr, r.ZEVMClient) if err != nil { return err } - runner.WZeta, err = wzeta.NewWETH9(runner.WZetaAddr, runner.ZEVMClient) + r.WZeta, err = wzeta.NewWETH9(r.WZetaAddr, r.ZEVMClient) if err != nil { return err } - runner.ZEVMSwapApp, err = zevmswap.NewZEVMSwapApp(runner.ZEVMSwapAppAddr, runner.ZEVMClient) + r.ZEVMSwapApp, err = zevmswap.NewZEVMSwapApp(r.ZEVMSwapAppAddr, r.ZEVMClient) if err != nil { return err } - runner.ContextApp, err = contextapp.NewContextApp(runner.ContextAppAddr, runner.ZEVMClient) + r.ContextApp, err = contextapp.NewContextApp(r.ContextAppAddr, r.ZEVMClient) if err != nil { return err } - runner.SystemContract, err = systemcontract.NewSystemContract(runner.SystemContractAddr, runner.ZEVMClient) + r.SystemContract, err = systemcontract.NewSystemContract(r.SystemContractAddr, r.ZEVMClient) if err != nil { return err } @@ -257,50 +262,55 @@ func (runner *E2ERunner) CopyAddressesFrom(other *E2ERunner) (err error) { } // Lock locks the mutex -func (runner *E2ERunner) Lock() { - runner.mutex.Lock() +func (r *E2ERunner) Lock() { + r.mutex.Lock() } // Unlock unlocks the mutex -func (runner *E2ERunner) Unlock() { - runner.mutex.Unlock() +func (r *E2ERunner) Unlock() { + r.mutex.Unlock() } // PrintContractAddresses prints the addresses of the contracts // the printed contracts are grouped in a zevm and evm section // there is a padding used to print the addresses at the same position -func (runner *E2ERunner) PrintContractAddresses() { +func (r *E2ERunner) PrintContractAddresses() { // zevm contracts - runner.Logger.Print(" --- 📜zEVM contracts ---") - runner.Logger.Print("SystemContract: %s", runner.SystemContractAddr.Hex()) - runner.Logger.Print("ETHZRC20: %s", runner.ETHZRC20Addr.Hex()) - runner.Logger.Print("ERC20ZRC20: %s", runner.ERC20ZRC20Addr.Hex()) - runner.Logger.Print("BTCZRC20: %s", runner.BTCZRC20Addr.Hex()) - runner.Logger.Print("UniswapFactory: %s", runner.UniswapV2FactoryAddr.Hex()) - runner.Logger.Print("UniswapRouter: %s", runner.UniswapV2RouterAddr.Hex()) - runner.Logger.Print("ConnectorZEVM: %s", runner.ConnectorZEVMAddr.Hex()) - runner.Logger.Print("WZeta: %s", runner.WZetaAddr.Hex()) - - runner.Logger.Print("ZEVMSwapApp: %s", runner.ZEVMSwapAppAddr.Hex()) - runner.Logger.Print("ContextApp: %s", runner.ContextAppAddr.Hex()) - runner.Logger.Print("TestDappZEVM: %s", runner.ZevmTestDAppAddr.Hex()) + r.Logger.Print(" --- 📜zEVM contracts ---") + r.Logger.Print("SystemContract: %s", r.SystemContractAddr.Hex()) + r.Logger.Print("ETHZRC20: %s", r.ETHZRC20Addr.Hex()) + r.Logger.Print("ERC20ZRC20: %s", r.ERC20ZRC20Addr.Hex()) + r.Logger.Print("BTCZRC20: %s", r.BTCZRC20Addr.Hex()) + r.Logger.Print("UniswapFactory: %s", r.UniswapV2FactoryAddr.Hex()) + r.Logger.Print("UniswapRouter: %s", r.UniswapV2RouterAddr.Hex()) + r.Logger.Print("ConnectorZEVM: %s", r.ConnectorZEVMAddr.Hex()) + r.Logger.Print("WZeta: %s", r.WZetaAddr.Hex()) + + r.Logger.Print("ZEVMSwapApp: %s", r.ZEVMSwapAppAddr.Hex()) + r.Logger.Print("ContextApp: %s", r.ContextAppAddr.Hex()) + r.Logger.Print("TestDappZEVM: %s", r.ZevmTestDAppAddr.Hex()) // evm contracts - runner.Logger.Print(" --- 📜EVM contracts ---") - runner.Logger.Print("ZetaEth: %s", runner.ZetaEthAddr.Hex()) - runner.Logger.Print("ConnectorEth: %s", runner.ConnectorEthAddr.Hex()) - runner.Logger.Print("ERC20Custody: %s", runner.ERC20CustodyAddr.Hex()) - runner.Logger.Print("ERC20: %s", runner.ERC20Addr.Hex()) - runner.Logger.Print("TestDappEVM: %s", runner.EvmTestDAppAddr.Hex()) + r.Logger.Print(" --- 📜EVM contracts ---") + r.Logger.Print("ZetaEth: %s", r.ZetaEthAddr.Hex()) + r.Logger.Print("ConnectorEth: %s", r.ConnectorEthAddr.Hex()) + r.Logger.Print("ERC20Custody: %s", r.ERC20CustodyAddr.Hex()) + r.Logger.Print("ERC20: %s", r.ERC20Addr.Hex()) + r.Logger.Print("TestDappEVM: %s", r.EvmTestDAppAddr.Hex()) } // Errorf logs an error message. Mimics the behavior of testing.T.Errorf -func (runner *E2ERunner) Errorf(format string, args ...any) { - runner.Logger.Error(format, args...) +func (r *E2ERunner) Errorf(format string, args ...any) { + r.Logger.Error(format, args...) } // FailNow implemented to mimic the behavior of testing.T.FailNow -func (runner *E2ERunner) FailNow() { - runner.Logger.Error("Test failed") +func (r *E2ERunner) FailNow() { + r.Logger.Error("Test failed") + r.CtxCancel() os.Exit(1) } + +func (r *E2ERunner) requireTxSuccessful(receipt *ethtypes.Receipt, msgAndArgs ...any) { + utils.RequireTxSuccessful(r, receipt, msgAndArgs...) +} diff --git a/e2e/runner/setup_bitcoin.go b/e2e/runner/setup_bitcoin.go index 8e39d0143e..92a7eac428 100644 --- a/e2e/runner/setup_bitcoin.go +++ b/e2e/runner/setup_bitcoin.go @@ -2,7 +2,6 @@ package runner import ( "encoding/hex" - "strings" "time" "github.com/btcsuite/btcd/btcec" @@ -11,58 +10,50 @@ import ( "github.com/stretchr/testify/require" ) -func (runner *E2ERunner) SetupBitcoinAccount(initNetwork bool) { - runner.Logger.Print("⚙️ setting up Bitcoin account") +func (r *E2ERunner) SetupBitcoinAccount(initNetwork bool) { + r.Logger.Print("⚙️ setting up Bitcoin account") startTime := time.Now() defer func() { - runner.Logger.Print("✅ Bitcoin account setup in %s\n", time.Since(startTime)) + r.Logger.Print("✅ Bitcoin account setup in %s\n", time.Since(startTime)) }() - _, err := runner.BtcRPCClient.CreateWallet(runner.Name, rpcclient.WithCreateWalletBlank()) + _, err := r.BtcRPCClient.CreateWallet(r.Name, rpcclient.WithCreateWalletBlank()) if err != nil { - if !strings.Contains(err.Error(), "Database already exists") { - panic(err) - } + require.ErrorContains(r, err, "Database already exists") } - runner.SetBtcAddress(runner.Name, true) + r.SetBtcAddress(r.Name, true) if initNetwork { // import the TSS address - err = runner.BtcRPCClient.ImportAddress(runner.BTCTSSAddress.EncodeAddress()) - if err != nil { - panic(err) - } + err = r.BtcRPCClient.ImportAddress(r.BTCTSSAddress.EncodeAddress()) + require.NoError(r, err) // mine some blocks to get some BTC into the deployer address - _, err = runner.GenerateToAddressIfLocalBitcoin(101, runner.BTCDeployerAddress) - if err != nil { - panic(err) - } - - _, err = runner.GenerateToAddressIfLocalBitcoin(4, runner.BTCDeployerAddress) - if err != nil { - panic(err) - } + _, err = r.GenerateToAddressIfLocalBitcoin(101, r.BTCDeployerAddress) + require.NoError(r, err) + + _, err = r.GenerateToAddressIfLocalBitcoin(4, r.BTCDeployerAddress) + require.NoError(r, err) } } // GetBtcAddress returns the BTC address of the deployer from its EVM private key -func (runner *E2ERunner) GetBtcAddress() (string, string, error) { - skBytes, err := hex.DecodeString(runner.DeployerPrivateKey) +func (r *E2ERunner) GetBtcAddress() (string, string, error) { + skBytes, err := hex.DecodeString(r.DeployerPrivateKey) if err != nil { return "", "", err } sk, _ := btcec.PrivKeyFromBytes(btcec.S256(), skBytes) - privkeyWIF, err := btcutil.NewWIF(sk, runner.BitcoinParams, true) + privkeyWIF, err := btcutil.NewWIF(sk, r.BitcoinParams, true) if err != nil { return "", "", err } address, err := btcutil.NewAddressWitnessPubKeyHash( btcutil.Hash160(privkeyWIF.SerializePubKey()), - runner.BitcoinParams, + r.BitcoinParams, ) if err != nil { return "", "", err @@ -73,30 +64,24 @@ func (runner *E2ERunner) GetBtcAddress() (string, string, error) { } // SetBtcAddress imports the deployer's private key into the Bitcoin node -func (runner *E2ERunner) SetBtcAddress(name string, rescan bool) { - skBytes, err := hex.DecodeString(runner.DeployerPrivateKey) - if err != nil { - panic(err) - } +func (r *E2ERunner) SetBtcAddress(name string, rescan bool) { + skBytes, err := hex.DecodeString(r.DeployerPrivateKey) + require.NoError(r, err) sk, _ := btcec.PrivKeyFromBytes(btcec.S256(), skBytes) - privkeyWIF, err := btcutil.NewWIF(sk, runner.BitcoinParams, true) - if err != nil { - panic(err) - } + privkeyWIF, err := btcutil.NewWIF(sk, r.BitcoinParams, true) + require.NoError(r, err) if rescan { - err := runner.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) - require.NoError(runner, err, "failed to execute ImportPrivKeyRescan") + err := r.BtcRPCClient.ImportPrivKeyRescan(privkeyWIF, name, true) + require.NoError(r, err, "failed to execute ImportPrivKeyRescan") } - runner.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash( + r.BTCDeployerAddress, err = btcutil.NewAddressWitnessPubKeyHash( btcutil.Hash160(privkeyWIF.PrivKey.PubKey().SerializeCompressed()), - runner.BitcoinParams, + r.BitcoinParams, ) - if err != nil { - panic(err) - } + require.NoError(r, err) - runner.Logger.Info("BTCDeployerAddress: %s", runner.BTCDeployerAddress.EncodeAddress()) + r.Logger.Info("BTCDeployerAddress: %s", r.BTCDeployerAddress.EncodeAddress()) } diff --git a/e2e/runner/setup_evm.go b/e2e/runner/setup_evm.go index 2bc0aeb70d..ff5b2e0ddc 100644 --- a/e2e/runner/setup_evm.go +++ b/e2e/runner/setup_evm.go @@ -5,6 +5,8 @@ import ( "time" ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/erc20custody.sol" zetaeth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zeta.eth.sol" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" @@ -21,181 +23,148 @@ const ( ) // SetEVMContractsFromConfig set EVM contracts for e2e test from the config -func (runner *E2ERunner) SetEVMContractsFromConfig() { +func (r *E2ERunner) SetEVMContractsFromConfig() { conf, err := config.ReadConfig(ContractsConfigFile) - if err != nil { - panic(err) - } + require.NoError(r, err) // Set ZetaEthAddr - runner.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddress) - runner.ZetaEth, err = zetaeth.NewZetaEth(runner.ZetaEthAddr, runner.EVMClient) - if err != nil { - panic(err) - } + r.ZetaEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ZetaEthAddress) + r.ZetaEth, err = zetaeth.NewZetaEth(r.ZetaEthAddr, r.EVMClient) + require.NoError(r, err) // Set ConnectorEthAddr - runner.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr) - runner.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(runner.ConnectorEthAddr, runner.EVMClient) - if err != nil { - panic(err) - } + r.ConnectorEthAddr = ethcommon.HexToAddress(conf.Contracts.EVM.ConnectorEthAddr) + r.ConnectorEth, err = zetaconnectoreth.NewZetaConnectorEth(r.ConnectorEthAddr, r.EVMClient) + require.NoError(r, err) } // SetupEVM setup contracts on EVM for e2e test -func (runner *E2ERunner) SetupEVM(contractsDeployed bool, whitelistERC20 bool) { - runner.Logger.Print("⚙️ setting up EVM network") +func (r *E2ERunner) SetupEVM(contractsDeployed bool, whitelistERC20 bool) { + r.Logger.Print("⚙️ setting up EVM network") startTime := time.Now() defer func() { - runner.Logger.Info("EVM setup took %s\n", time.Since(startTime)) + r.Logger.Info("EVM setup took %s\n", time.Since(startTime)) }() // TODO: put this logic outside of this function // We use this config to be consistent with the old implementation // https://github.com/zeta-chain/node-private/issues/41 if contractsDeployed { - runner.SetEVMContractsFromConfig() + r.SetEVMContractsFromConfig() return } conf := config.DefaultConfig() - runner.Logger.InfoLoud("Deploy ZetaETH ConnectorETH ERC20Custody ERC20\n") + r.Logger.InfoLoud("Deploy ZetaETH ConnectorETH ERC20Custody ERC20\n") // donate to the TSS address to avoid account errors because deploying gas token ZRC20 will automatically mint // gas token on ZetaChain to initialize the pool - txDonation, err := runner.SendEther( - runner.TSSAddress, - big.NewInt(101000000000000000), - []byte(constant.DonationMessage), - ) - if err != nil { - panic(err) - } + txDonation, err := r.SendEther(r.TSSAddress, big.NewInt(101000000000000000), []byte(constant.DonationMessage)) + require.NoError(r, err) - runner.Logger.Info("Deploying ZetaEth contract") + r.Logger.Info("Deploying ZetaEth contract") zetaEthAddr, txZetaEth, ZetaEth, err := zetaeth.DeployZetaEth( - runner.EVMAuth, - runner.EVMClient, - runner.DeployerAddress, + r.EVMAuth, + r.EVMClient, + r.DeployerAddress, big.NewInt(21_000_000_000), ) - if err != nil { - panic(err) - } - runner.ZetaEth = ZetaEth - runner.ZetaEthAddr = zetaEthAddr + require.NoError(r, err) + + r.ZetaEth = ZetaEth + r.ZetaEthAddr = zetaEthAddr conf.Contracts.EVM.ZetaEthAddress = zetaEthAddr.String() - runner.Logger.Info("ZetaEth contract address: %s, tx hash: %s", zetaEthAddr.Hex(), zetaEthAddr.Hash().Hex()) + r.Logger.Info("ZetaEth contract address: %s, tx hash: %s", zetaEthAddr.Hex(), zetaEthAddr.Hash().Hex()) - runner.Logger.Info("Deploying ZetaConnectorEth contract") + r.Logger.Info("Deploying ZetaConnectorEth contract") connectorEthAddr, txConnector, ConnectorEth, err := zetaconnectoreth.DeployZetaConnectorEth( - runner.EVMAuth, - runner.EVMClient, + r.EVMAuth, + r.EVMClient, zetaEthAddr, - runner.TSSAddress, - runner.DeployerAddress, - runner.DeployerAddress, + r.TSSAddress, + r.DeployerAddress, + r.DeployerAddress, ) - if err != nil { - panic(err) - } - runner.ConnectorEth = ConnectorEth - runner.ConnectorEthAddr = connectorEthAddr + require.NoError(r, err) + + r.ConnectorEth = ConnectorEth + r.ConnectorEthAddr = connectorEthAddr conf.Contracts.EVM.ConnectorEthAddr = connectorEthAddr.String() - runner.Logger.Info( + r.Logger.Info( "ZetaConnectorEth contract address: %s, tx hash: %s", connectorEthAddr.Hex(), txConnector.Hash().Hex(), ) - runner.Logger.Info("Deploying ERC20Custody contract") + r.Logger.Info("Deploying ERC20Custody contract") erc20CustodyAddr, txCustody, ERC20Custody, err := erc20custody.DeployERC20Custody( - runner.EVMAuth, - runner.EVMClient, - runner.DeployerAddress, - runner.DeployerAddress, + r.EVMAuth, + r.EVMClient, + r.DeployerAddress, + r.DeployerAddress, big.NewInt(0), big.NewInt(1e18), ethcommon.HexToAddress("0x"), ) - if err != nil { - panic(err) - } - runner.ERC20CustodyAddr = erc20CustodyAddr - runner.ERC20Custody = ERC20Custody - runner.Logger.Info("ERC20Custody contract address: %s, tx hash: %s", erc20CustodyAddr.Hex(), txCustody.Hash().Hex()) - - runner.Logger.Info("Deploying ERC20 contract") - erc20Addr, txERC20, erc20, err := erc20.DeployERC20(runner.EVMAuth, runner.EVMClient, "TESTERC20", "TESTERC20", 6) - if err != nil { - panic(err) - } - runner.ERC20 = erc20 - runner.ERC20Addr = erc20Addr - runner.Logger.Info("ERC20 contract address: %s, tx hash: %s", erc20Addr.Hex(), txERC20.Hash().Hex()) + require.NoError(r, err) + + r.ERC20CustodyAddr = erc20CustodyAddr + r.ERC20Custody = ERC20Custody + r.Logger.Info("ERC20Custody contract address: %s, tx hash: %s", erc20CustodyAddr.Hex(), txCustody.Hash().Hex()) + + r.Logger.Info("Deploying ERC20 contract") + erc20Addr, txERC20, erc20, err := erc20.DeployERC20(r.EVMAuth, r.EVMClient, "TESTERC20", "TESTERC20", 6) + require.NoError(r, err) + + r.ERC20 = erc20 + r.ERC20Addr = erc20Addr + r.Logger.Info("ERC20 contract address: %s, tx hash: %s", erc20Addr.Hex(), txERC20.Hash().Hex()) // deploy TestDApp contract appAddr, txApp, _, err := testdapp.DeployTestDApp( - runner.EVMAuth, - runner.EVMClient, - runner.ConnectorEthAddr, - runner.ZetaEthAddr, + r.EVMAuth, + r.EVMClient, + r.ConnectorEthAddr, + r.ZetaEthAddr, ) - if err != nil { - panic(err) + require.NoError(r, err) + + r.EvmTestDAppAddr = appAddr + r.Logger.Info("TestDApp contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) + + ensureTxReceipt := func(tx *ethtypes.Transaction, failMessage string) { + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt, failMessage) } - runner.EvmTestDAppAddr = appAddr - runner.Logger.Info("TestDApp contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) // check contract deployment receipt - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txDonation, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("EVM donation tx failed") - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txZetaEth, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ZetaEth deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txConnector, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ZetaConnectorEth deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txCustody, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ERC20Custody deployment failed") - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txERC20, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ERC20 deployment failed") - } - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txApp, runner.Logger, runner.ReceiptTimeout) - if receipt.Status != 1 { - panic("TestDApp deployment failed") - } + ensureTxReceipt(txDonation, "EVM donation tx failed") + ensureTxReceipt(txZetaEth, "ZetaEth deployment failed") + ensureTxReceipt(txConnector, "ZetaConnectorEth deployment failed") + ensureTxReceipt(txCustody, "ERC20Custody deployment failed") + ensureTxReceipt(txERC20, "ERC20 deployment failed") + ensureTxReceipt(txApp, "TestDApp deployment failed") // initialize custody contract - runner.Logger.Info("Whitelist ERC20") + r.Logger.Info("Whitelist ERC20") if whitelistERC20 { - txWhitelist, err := ERC20Custody.Whitelist(runner.EVMAuth, erc20Addr) - if err != nil { - panic(err) - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txWhitelist, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ERC20 whitelist failed") - } + txWhitelist, err := ERC20Custody.Whitelist(r.EVMAuth, erc20Addr) + require.NoError(r, err) + ensureTxReceipt(txWhitelist, "ERC20 whitelist failed") } - runner.Logger.Info("Set TSS address") - txCustody, err = ERC20Custody.UpdateTSSAddress(runner.EVMAuth, runner.TSSAddress) - if err != nil { - panic(err) - } - if receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, txCustody, runner.Logger, runner.ReceiptTimeout); receipt.Status != 1 { - panic("ERC20 update TSS address failed") - } - runner.Logger.Info("TSS set receipt tx hash: %s", txCustody.Hash().Hex()) + r.Logger.Info("Set TSS address") + txCustody, err = ERC20Custody.UpdateTSSAddress(r.EVMAuth, r.TSSAddress) + require.NoError(r, err) + + ensureTxReceipt(txCustody, "ERC20 update TSS address failed") + + r.Logger.Info("TSS set receipt tx hash: %s", txCustody.Hash().Hex()) // save config containing contract addresses // TODO: put this logic outside of this function in a general config // We use this config to be consistent with the old implementation // https://github.com/zeta-chain/node-private/issues/41 - if err := config.WriteConfig(ContractsConfigFile, conf); err != nil { - panic(err) - } + require.NoError(r, config.WriteConfig(ContractsConfigFile, conf)) } diff --git a/e2e/runner/setup_zeta.go b/e2e/runner/setup_zeta.go index ac24c02de2..ef3acbd64b 100644 --- a/e2e/runner/setup_zeta.go +++ b/e2e/runner/setup_zeta.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" connectorzevm "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zetaconnectorzevm.sol" @@ -29,23 +30,23 @@ import ( var EmissionsPoolFunding = big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(2e7)) // SetTSSAddresses set TSS addresses from information queried from ZetaChain -func (runner *E2ERunner) SetTSSAddresses() error { - runner.Logger.Print("⚙️ setting up TSS address") +func (r *E2ERunner) SetTSSAddresses() error { + r.Logger.Print("⚙️ setting up TSS address") - btcChainID, err := chains.GetBTCChainIDFromChainParams(runner.BitcoinParams) + btcChainID, err := chains.GetBTCChainIDFromChainParams(r.BitcoinParams) if err != nil { return err } res := &observertypes.QueryGetTssAddressResponse{} for i := 0; ; i++ { - res, err = runner.ObserverClient.GetTssAddress(runner.Ctx, &observertypes.QueryGetTssAddressRequest{ + res, err = r.ObserverClient.GetTssAddress(r.Ctx, &observertypes.QueryGetTssAddressRequest{ BitcoinChainId: btcChainID, }) if err != nil { if i%10 == 0 { - runner.Logger.Info("ObserverClient.TSS error %s", err.Error()) - runner.Logger.Info("TSS not ready yet, waiting for TSS to be appear in zetacore network...") + r.Logger.Info("ObserverClient.TSS error %s", err.Error()) + r.Logger.Info("TSS not ready yet, waiting for TSS to be appear in zetacore network...") } time.Sleep(1 * time.Second) continue @@ -55,199 +56,165 @@ func (runner *E2ERunner) SetTSSAddresses() error { tssAddress := ethcommon.HexToAddress(res.Eth) - btcTSSAddress, err := btcutil.DecodeAddress(res.Btc, runner.BitcoinParams) - if err != nil { - panic(err) - } + btcTSSAddress, err := btcutil.DecodeAddress(res.Btc, r.BitcoinParams) + require.NoError(r, err) - runner.TSSAddress = tssAddress - runner.BTCTSSAddress = btcTSSAddress + r.TSSAddress = tssAddress + r.BTCTSSAddress = btcTSSAddress return nil } // SetZEVMContracts set contracts for the ZEVM -func (runner *E2ERunner) SetZEVMContracts() { - runner.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") +func (r *E2ERunner) SetZEVMContracts() { + r.Logger.Print("⚙️ deploying system contracts and ZRC20s on ZEVM") startTime := time.Now() defer func() { - runner.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) + r.Logger.Info("System contract deployments took %s\n", time.Since(startTime)) }() // deploy system contracts and ZRC20 contracts on ZetaChain - uniswapV2FactoryAddr, uniswapV2RouterAddr, zevmConnectorAddr, wzetaAddr, erc20zrc20Addr, err := runner.ZetaTxServer.DeploySystemContractsAndZRC20( + uniswapV2FactoryAddr, uniswapV2RouterAddr, zevmConnectorAddr, wzetaAddr, erc20zrc20Addr, err := r.ZetaTxServer.DeploySystemContractsAndZRC20( e2eutils.FungibleAdminName, - runner.ERC20Addr.Hex(), + r.ERC20Addr.Hex(), ) - if err != nil { - panic(err) - } + require.NoError(r, err) // Set ERC20ZRC20Addr - runner.ERC20ZRC20Addr = ethcommon.HexToAddress(erc20zrc20Addr) - runner.ERC20ZRC20, err = zrc20.NewZRC20(runner.ERC20ZRC20Addr, runner.ZEVMClient) - if err != nil { - panic(err) - } + r.ERC20ZRC20Addr = ethcommon.HexToAddress(erc20zrc20Addr) + r.ERC20ZRC20, err = zrc20.NewZRC20(r.ERC20ZRC20Addr, r.ZEVMClient) + require.NoError(r, err) // UniswapV2FactoryAddr - runner.UniswapV2FactoryAddr = ethcommon.HexToAddress(uniswapV2FactoryAddr) - runner.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(runner.UniswapV2FactoryAddr, runner.ZEVMClient) - if err != nil { - panic(err) - } + r.UniswapV2FactoryAddr = ethcommon.HexToAddress(uniswapV2FactoryAddr) + r.UniswapV2Factory, err = uniswapv2factory.NewUniswapV2Factory(r.UniswapV2FactoryAddr, r.ZEVMClient) + require.NoError(r, err) // UniswapV2RouterAddr - runner.UniswapV2RouterAddr = ethcommon.HexToAddress(uniswapV2RouterAddr) - runner.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(runner.UniswapV2RouterAddr, runner.ZEVMClient) - if err != nil { - panic(err) - } + r.UniswapV2RouterAddr = ethcommon.HexToAddress(uniswapV2RouterAddr) + r.UniswapV2Router, err = uniswapv2router.NewUniswapV2Router02(r.UniswapV2RouterAddr, r.ZEVMClient) + require.NoError(r, err) // ZevmConnectorAddr - runner.ConnectorZEVMAddr = ethcommon.HexToAddress(zevmConnectorAddr) - runner.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(runner.ConnectorZEVMAddr, runner.ZEVMClient) - if err != nil { - panic(err) - } + r.ConnectorZEVMAddr = ethcommon.HexToAddress(zevmConnectorAddr) + r.ConnectorZEVM, err = connectorzevm.NewZetaConnectorZEVM(r.ConnectorZEVMAddr, r.ZEVMClient) + require.NoError(r, err) // WZetaAddr - runner.WZetaAddr = ethcommon.HexToAddress(wzetaAddr) - runner.WZeta, err = wzeta.NewWETH9(runner.WZetaAddr, runner.ZEVMClient) - if err != nil { - panic(err) - } + r.WZetaAddr = ethcommon.HexToAddress(wzetaAddr) + r.WZeta, err = wzeta.NewWETH9(r.WZetaAddr, r.ZEVMClient) + require.NoError(r, err) // query system contract address from the chain - systemContractRes, err := runner.FungibleClient.SystemContract( - runner.Ctx, + systemContractRes, err := r.FungibleClient.SystemContract( + r.Ctx, &fungibletypes.QueryGetSystemContractRequest{}, ) - if err != nil { - panic(err) - } - systemContractAddr := ethcommon.HexToAddress(systemContractRes.SystemContract.SystemContract) + require.NoError(r, err) - SystemContract, err := systemcontract.NewSystemContract( + systemContractAddr := ethcommon.HexToAddress(systemContractRes.SystemContract.SystemContract) + systemContract, err := systemcontract.NewSystemContract( systemContractAddr, - runner.ZEVMClient, + r.ZEVMClient, ) - if err != nil { - panic(err) - } + require.NoError(r, err) - runner.SystemContract = SystemContract - runner.SystemContractAddr = systemContractAddr + r.SystemContract = systemContract + r.SystemContractAddr = systemContractAddr // set ZRC20 contracts - runner.SetupETHZRC20() - runner.SetupBTCZRC20() + r.SetupETHZRC20() + r.SetupBTCZRC20() // deploy TestDApp contract on zEVM appAddr, txApp, _, err := testdapp.DeployTestDApp( - runner.ZEVMAuth, - runner.ZEVMClient, - runner.ConnectorZEVMAddr, - runner.WZetaAddr, + r.ZEVMAuth, + r.ZEVMClient, + r.ConnectorZEVMAddr, + r.WZetaAddr, ) - if err != nil { - panic(err) - } - runner.ZevmTestDAppAddr = appAddr - runner.Logger.Info("TestDApp Zevm contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) + require.NoError(r, err) + + r.ZevmTestDAppAddr = appAddr + r.Logger.Info("TestDApp Zevm contract address: %s, tx hash: %s", appAddr.Hex(), txApp.Hash().Hex()) // deploy ZEVMSwapApp and ContextApp zevmSwapAppAddr, txZEVMSwapApp, zevmSwapApp, err := zevmswap.DeployZEVMSwapApp( - runner.ZEVMAuth, - runner.ZEVMClient, - runner.UniswapV2RouterAddr, - runner.SystemContractAddr, + r.ZEVMAuth, + r.ZEVMClient, + r.UniswapV2RouterAddr, + r.SystemContractAddr, ) - if err != nil { - panic(err) - } + require.NoError(r, err) - contextAppAddr, txContextApp, contextApp, err := contextapp.DeployContextApp(runner.ZEVMAuth, runner.ZEVMClient) - if err != nil { - panic(err) - } + contextAppAddr, txContextApp, contextApp, err := contextapp.DeployContextApp(r.ZEVMAuth, r.ZEVMClient) + require.NoError(r, err) receipt := e2eutils.MustWaitForTxReceipt( - runner.Ctx, - runner.ZEVMClient, + r.Ctx, + r.ZEVMClient, txZEVMSwapApp, - runner.Logger, - runner.ReceiptTimeout, + r.Logger, + r.ReceiptTimeout, ) - if receipt.Status != 1 { - panic("ZEVMSwapApp deployment failed") - } - runner.ZEVMSwapAppAddr = zevmSwapAppAddr - runner.ZEVMSwapApp = zevmSwapApp + r.requireTxSuccessful(receipt, "ZEVMSwapApp deployment failed") + + r.ZEVMSwapAppAddr = zevmSwapAppAddr + r.ZEVMSwapApp = zevmSwapApp receipt = e2eutils.MustWaitForTxReceipt( - runner.Ctx, - runner.ZEVMClient, + r.Ctx, + r.ZEVMClient, txContextApp, - runner.Logger, - runner.ReceiptTimeout, + r.Logger, + r.ReceiptTimeout, ) - if receipt.Status != 1 { - panic("ContextApp deployment failed") - } - runner.ContextAppAddr = contextAppAddr - runner.ContextApp = contextApp + r.requireTxSuccessful(receipt, "ContextApp deployment failed") + r.ContextAppAddr = contextAppAddr + r.ContextApp = contextApp } // SetupETHZRC20 sets up the ETH ZRC20 in the runner from the values queried from the chain -func (runner *E2ERunner) SetupETHZRC20() { - ethZRC20Addr, err := runner.SystemContract.GasCoinZRC20ByChainId( +func (r *E2ERunner) SetupETHZRC20() { + ethZRC20Addr, err := r.SystemContract.GasCoinZRC20ByChainId( &bind.CallOpts{}, big.NewInt(chains.GoerliLocalnet.ChainId), ) - if err != nil { - panic(err) - } - if (ethZRC20Addr == ethcommon.Address{}) { - panic("eth zrc20 not found") - } - runner.ETHZRC20Addr = ethZRC20Addr - ethZRC20, err := zrc20.NewZRC20(ethZRC20Addr, runner.ZEVMClient) - if err != nil { - panic(err) - } - runner.ETHZRC20 = ethZRC20 + require.NoError(r, err) + require.NotEqual(r, ethcommon.Address{}, ethZRC20Addr, "eth zrc20 not found") + + r.ETHZRC20Addr = ethZRC20Addr + ethZRC20, err := zrc20.NewZRC20(ethZRC20Addr, r.ZEVMClient) + require.NoError(r, err) + + r.ETHZRC20 = ethZRC20 } // SetupBTCZRC20 sets up the BTC ZRC20 in the runner from the values queried from the chain -func (runner *E2ERunner) SetupBTCZRC20() { - BTCZRC20Addr, err := runner.SystemContract.GasCoinZRC20ByChainId( +func (r *E2ERunner) SetupBTCZRC20() { + BTCZRC20Addr, err := r.SystemContract.GasCoinZRC20ByChainId( &bind.CallOpts{}, big.NewInt(chains.BitcoinRegtest.ChainId), ) - if err != nil { - panic(err) - } - runner.BTCZRC20Addr = BTCZRC20Addr - runner.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) - BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, runner.ZEVMClient) - if err != nil { - panic(err) - } - runner.BTCZRC20 = BTCZRC20 + require.NoError(r, err) + r.BTCZRC20Addr = BTCZRC20Addr + r.Logger.Info("BTCZRC20Addr: %s", BTCZRC20Addr.Hex()) + BTCZRC20, err := zrc20.NewZRC20(BTCZRC20Addr, r.ZEVMClient) + require.NoError(r, err) + r.BTCZRC20 = BTCZRC20 } // EnableHeaderVerification enables the header verification for the given chain IDs -func (runner *E2ERunner) EnableHeaderVerification(chainIDList []int64) error { - runner.Logger.Print("⚙️ enabling verification flags for block headers") +func (r *E2ERunner) EnableHeaderVerification(chainIDList []int64) error { + r.Logger.Print("⚙️ enabling verification flags for block headers") - return runner.ZetaTxServer.EnableHeaderVerification(e2eutils.FungibleAdminName, chainIDList) + return r.ZetaTxServer.EnableHeaderVerification(e2eutils.FungibleAdminName, chainIDList) } // FundEmissionsPool funds the emissions pool on ZetaChain with the same value as used originally on mainnet (20M ZETA) -func (runner *E2ERunner) FundEmissionsPool() error { - runner.Logger.Print("⚙️ funding the emissions pool on ZetaChain with 20M ZETA (%s)", txserver.EmissionsPoolAddress) +func (r *E2ERunner) FundEmissionsPool() error { + r.Logger.Print("⚙️ funding the emissions pool on ZetaChain with 20M ZETA (%s)", txserver.EmissionsPoolAddress) - return runner.ZetaTxServer.FundEmissionsPool(e2eutils.FungibleAdminName, EmissionsPoolFunding) + return r.ZetaTxServer.FundEmissionsPool(e2eutils.FungibleAdminName, EmissionsPoolFunding) } diff --git a/e2e/runner/zeta.go b/e2e/runner/zeta.go index 104fb4900f..726f3f5cb6 100644 --- a/e2e/runner/zeta.go +++ b/e2e/runner/zeta.go @@ -1,11 +1,11 @@ package runner import ( - "fmt" "math/big" ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" zetaconnectoreth "github.com/zeta-chain/protocol-contracts/pkg/contracts/evm/zetaconnector.eth.sol" connectorzevm "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zetaconnectorzevm.sol" @@ -14,103 +14,77 @@ import ( ) // WaitForTxReceiptOnZEVM waits for a tx receipt on ZEVM -func (runner *E2ERunner) WaitForTxReceiptOnZEVM(tx *ethtypes.Transaction) { - defer func() { - runner.Unlock() - }() - runner.Lock() - - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status != 1 { - panic("tx failed") - } +func (r *E2ERunner) WaitForTxReceiptOnZEVM(tx *ethtypes.Transaction) { + r.Lock() + defer r.Unlock() + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt) } // WaitForMinedCCTX waits for a cctx to be mined from a tx -func (runner *E2ERunner) WaitForMinedCCTX(txHash ethcommon.Hash) { - defer func() { - runner.Unlock() - }() - runner.Lock() +func (r *E2ERunner) WaitForMinedCCTX(txHash ethcommon.Hash) { + r.Lock() + defer r.Unlock() cctx := utils.WaitCctxMinedByInboundHash( - runner.Ctx, + r.Ctx, txHash.Hex(), - runner.CctxClient, - runner.Logger, - runner.CctxTimeout, + r.CctxClient, + r.Logger, + r.CctxTimeout, ) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected cctx status to be mined; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined) } // WaitForMinedCCTXFromIndex waits for a cctx to be mined from its index -func (runner *E2ERunner) WaitForMinedCCTXFromIndex(index string) { - defer func() { - runner.Unlock() - }() - runner.Lock() - - cctx := utils.WaitCCTXMinedByIndex(runner.Ctx, index, runner.CctxClient, runner.Logger, runner.CctxTimeout) - if cctx.CctxStatus.Status != types.CctxStatus_OutboundMined { - panic(fmt.Sprintf("expected cctx status to be mined; got %s, message: %s", - cctx.CctxStatus.Status.String(), - cctx.CctxStatus.StatusMessage), - ) - } +func (r *E2ERunner) WaitForMinedCCTXFromIndex(index string) { + r.Lock() + defer r.Unlock() + + cctx := utils.WaitCCTXMinedByIndex(r.Ctx, index, r.CctxClient, r.Logger, r.CctxTimeout) + utils.RequireCCTXStatus(r, cctx, types.CctxStatus_OutboundMined) } // SendZetaOnEvm sends ZETA to an address on EVM // this allows the ZETA contract deployer to funds other accounts on EVM -func (runner *E2ERunner) SendZetaOnEvm(address ethcommon.Address, zetaAmount int64) *ethtypes.Transaction { +func (r *E2ERunner) SendZetaOnEvm(address ethcommon.Address, zetaAmount int64) *ethtypes.Transaction { // the deployer might be sending ZETA in different goroutines - defer func() { - runner.Unlock() - }() - runner.Lock() + r.Lock() + defer r.Unlock() amount := big.NewInt(1e18) amount = amount.Mul(amount, big.NewInt(zetaAmount)) - tx, err := runner.ZetaEth.Transfer(runner.EVMAuth, address, amount) - if err != nil { - panic(err) - } + tx, err := r.ZetaEth.Transfer(r.EVMAuth, address, amount) + require.NoError(r, err) + return tx } // DepositZeta deposits ZETA on ZetaChain from the ZETA smart contract on EVM -func (runner *E2ERunner) DepositZeta() ethcommon.Hash { +func (r *E2ERunner) DepositZeta() ethcommon.Hash { amount := big.NewInt(1e18) amount = amount.Mul(amount, big.NewInt(100)) // 100 Zeta - return runner.DepositZetaWithAmount(runner.DeployerAddress, amount) + return r.DepositZetaWithAmount(r.DeployerAddress, amount) } // DepositZetaWithAmount deposits ZETA on ZetaChain from the ZETA smart contract on EVM with the specified amount -func (runner *E2ERunner) DepositZetaWithAmount(to ethcommon.Address, amount *big.Int) ethcommon.Hash { - tx, err := runner.ZetaEth.Approve(runner.EVMAuth, runner.ConnectorEthAddr, amount) - if err != nil { - panic(err) - } - runner.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) +func (r *E2ERunner) DepositZetaWithAmount(to ethcommon.Address, amount *big.Int) ethcommon.Hash { + tx, err := r.ZetaEth.Approve(r.EVMAuth, r.ConnectorEthAddr, amount) + require.NoError(r, err) - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.EVMReceipt(*receipt, "approve") - if receipt.Status != 1 { - panic("approve tx failed") - } + r.Logger.Info("Approve tx hash: %s", tx.Hash().Hex()) + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "approve") + r.requireTxSuccessful(receipt, "approve tx failed") // query the chain ID using zevm client - zetaChainID, err := runner.ZEVMClient.ChainID(runner.Ctx) - if err != nil { - panic(err) - } + zetaChainID, err := r.ZEVMClient.ChainID(r.Ctx) + require.NoError(r, err) - tx, err = runner.ConnectorEth.Send(runner.EVMAuth, zetaconnectoreth.ZetaInterfacesSendInput{ + tx, err = r.ConnectorEth.Send(r.EVMAuth, zetaconnectoreth.ZetaInterfacesSendInput{ // TODO: allow user to specify destination chain id // https://github.com/zeta-chain/node-private/issues/41 DestinationChainId: zetaChainID, @@ -120,27 +94,24 @@ func (runner *E2ERunner) DepositZetaWithAmount(to ethcommon.Address, amount *big ZetaValueAndGas: amount, ZetaParams: nil, }) - if err != nil { - panic(err) - } - runner.Logger.Info("Send tx hash: %s", tx.Hash().Hex()) + require.NoError(r, err) - receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.EVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.EVMReceipt(*receipt, "send") - if receipt.Status != 1 { - panic(fmt.Sprintf("expected tx receipt status to be 1; got %d", receipt.Status)) - } + r.Logger.Info("Send tx hash: %s", tx.Hash().Hex()) - runner.Logger.Info(" Logs:") + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.EVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "send") + r.requireTxSuccessful(receipt, "send tx failed") + + r.Logger.Info(" Logs:") for _, log := range receipt.Logs { - sentLog, err := runner.ConnectorEth.ParseZetaSent(*log) + sentLog, err := r.ConnectorEth.ParseZetaSent(*log) if err == nil { - runner.Logger.Info(" Connector: %s", runner.ConnectorEthAddr.String()) - runner.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - runner.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - runner.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - runner.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) - runner.Logger.Info(" Block Num: %d", log.BlockNumber) + r.Logger.Info(" Connector: %s", r.ConnectorEthAddr.String()) + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + r.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + r.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + r.Logger.Info(" Block Num: %d", log.BlockNumber) } } @@ -148,71 +119,59 @@ func (runner *E2ERunner) DepositZetaWithAmount(to ethcommon.Address, amount *big } // DepositAndApproveWZeta deposits and approves WZETA on ZetaChain from the ZETA smart contract on ZEVM -func (runner *E2ERunner) DepositAndApproveWZeta(amount *big.Int) { - runner.ZEVMAuth.Value = amount - tx, err := runner.WZeta.Deposit(runner.ZEVMAuth) - if err != nil { - panic(err) - } - runner.ZEVMAuth.Value = big.NewInt(0) - runner.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) +func (r *E2ERunner) DepositAndApproveWZeta(amount *big.Int) { + r.ZEVMAuth.Value = amount + tx, err := r.WZeta.Deposit(r.ZEVMAuth) + require.NoError(r, err) - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.EVMReceipt(*receipt, "wzeta deposit") - if receipt.Status == 0 { - panic("deposit failed") - } + r.ZEVMAuth.Value = big.NewInt(0) + r.Logger.Info("wzeta deposit tx hash: %s", tx.Hash().Hex()) - tx, err = runner.WZeta.Approve(runner.ZEVMAuth, runner.ConnectorZEVMAddr, amount) - if err != nil { - panic(err) - } - runner.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "wzeta deposit") + r.requireTxSuccessful(receipt, "deposit failed") - receipt = utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.EVMReceipt(*receipt, "wzeta approve") - if receipt.Status == 0 { - panic(fmt.Sprintf("approve failed, logs: %+v", receipt.Logs)) - } + tx, err = r.WZeta.Approve(r.ZEVMAuth, r.ConnectorZEVMAddr, amount) + require.NoError(r, err) + + r.Logger.Info("wzeta approve tx hash: %s", tx.Hash().Hex()) + + receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "wzeta approve") + r.requireTxSuccessful(receipt, "approve failed, logs: %+v", receipt.Logs) } // WithdrawZeta withdraws ZETA from ZetaChain to the ZETA smart contract on EVM // waitReceipt specifies whether to wait for the tx receipt and check if the tx was successful -func (runner *E2ERunner) WithdrawZeta(amount *big.Int, waitReceipt bool) *ethtypes.Transaction { - chainID, err := runner.EVMClient.ChainID(runner.Ctx) - if err != nil { - panic(err) - } +func (r *E2ERunner) WithdrawZeta(amount *big.Int, waitReceipt bool) *ethtypes.Transaction { + chainID, err := r.EVMClient.ChainID(r.Ctx) + require.NoError(r, err) - tx, err := runner.ConnectorZEVM.Send(runner.ZEVMAuth, connectorzevm.ZetaInterfacesSendInput{ + tx, err := r.ConnectorZEVM.Send(r.ZEVMAuth, connectorzevm.ZetaInterfacesSendInput{ DestinationChainId: chainID, - DestinationAddress: runner.DeployerAddress.Bytes(), + DestinationAddress: r.DeployerAddress.Bytes(), DestinationGasLimit: big.NewInt(400_000), Message: nil, ZetaValueAndGas: amount, ZetaParams: nil, }) - if err != nil { - panic(err) - } - runner.Logger.Info("send tx hash: %s", tx.Hash().Hex()) + require.NoError(r, err) - if waitReceipt { - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.EVMReceipt(*receipt, "send") - if receipt.Status == 0 { - panic(fmt.Sprintf("send failed, logs: %+v", receipt.Logs)) + r.Logger.Info("send tx hash: %s", tx.Hash().Hex()) - } + if waitReceipt { + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.EVMReceipt(*receipt, "send") + r.requireTxSuccessful(receipt, "send failed, logs: %+v", receipt.Logs) - runner.Logger.Info(" Logs:") + r.Logger.Info(" Logs:") for _, log := range receipt.Logs { - sentLog, err := runner.ConnectorZEVM.ParseZetaSent(*log) + sentLog, err := r.ConnectorZEVM.ParseZetaSent(*log) if err == nil { - runner.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) - runner.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) - runner.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) - runner.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) + r.Logger.Info(" Dest Addr: %s", ethcommon.BytesToAddress(sentLog.DestinationAddress).Hex()) + r.Logger.Info(" Dest Chain: %d", sentLog.DestinationChainId) + r.Logger.Info(" Dest Gas: %d", sentLog.DestinationGasLimit) + r.Logger.Info(" Zeta Value: %d", sentLog.ZetaValueAndGas) } } } @@ -221,40 +180,37 @@ func (runner *E2ERunner) WithdrawZeta(amount *big.Int, waitReceipt bool) *ethtyp } // WithdrawEther withdraws Ether from ZetaChain to the ZETA smart contract on EVM -func (runner *E2ERunner) WithdrawEther(amount *big.Int) *ethtypes.Transaction { +func (r *E2ERunner) WithdrawEther(amount *big.Int) *ethtypes.Transaction { // withdraw - tx, err := runner.ETHZRC20.Withdraw(runner.ZEVMAuth, runner.DeployerAddress.Bytes(), amount) - if err != nil { - panic(err) - } - runner.Logger.EVMTransaction(*tx, "withdraw") + tx, err := r.ETHZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), amount) + require.NoError(r, err) - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - if receipt.Status == 0 { - panic("withdraw failed") - } - runner.Logger.EVMReceipt(*receipt, "withdraw") - runner.Logger.ZRC20Withdrawal(runner.ETHZRC20, *receipt, "withdraw") + r.Logger.EVMTransaction(*tx, "withdraw") + + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.requireTxSuccessful(receipt, "withdraw failed") + + r.Logger.EVMReceipt(*receipt, "withdraw") + r.Logger.ZRC20Withdrawal(r.ETHZRC20, *receipt, "withdraw") return tx } // WithdrawERC20 withdraws an ERC20 token from ZetaChain to the ZETA smart contract on EVM -func (runner *E2ERunner) WithdrawERC20(amount *big.Int) *ethtypes.Transaction { - tx, err := runner.ERC20ZRC20.Withdraw(runner.ZEVMAuth, runner.DeployerAddress.Bytes(), amount) - if err != nil { - panic(err) - } - runner.Logger.EVMTransaction(*tx, "withdraw") +func (r *E2ERunner) WithdrawERC20(amount *big.Int) *ethtypes.Transaction { + tx, err := r.ERC20ZRC20.Withdraw(r.ZEVMAuth, r.DeployerAddress.Bytes(), amount) + require.NoError(r, err) + + r.Logger.EVMTransaction(*tx, "withdraw") - receipt := utils.MustWaitForTxReceipt(runner.Ctx, runner.ZEVMClient, tx, runner.Logger, runner.ReceiptTimeout) - runner.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) + receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) + r.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status) for _, log := range receipt.Logs { - event, err := runner.ERC20ZRC20.ParseWithdrawal(*log) + event, err := r.ERC20ZRC20.ParseWithdrawal(*log) if err != nil { continue } - runner.Logger.Info( + r.Logger.Info( " logs: from %s, to %x, value %d, gasfee %d", event.From.Hex(), event.To, diff --git a/e2e/txserver/zeta_tx_server.go b/e2e/txserver/zeta_tx_server.go index fb2c403ada..b6f19a5807 100644 --- a/e2e/txserver/zeta_tx_server.go +++ b/e2e/txserver/zeta_tx_server.go @@ -156,7 +156,6 @@ func (zts ZetaTxServer) GetAccountAddressFromName(name string) (string, error) { // GetAllAccountAddress returns all account addresses func (zts ZetaTxServer) GetAllAccountAddress() []string { return zts.address - } // GetAccountMnemonic returns the account name from the given index diff --git a/e2e/utils/evm.go b/e2e/utils/evm.go index fc6792d617..45b2a55890 100644 --- a/e2e/utils/evm.go +++ b/e2e/utils/evm.go @@ -11,6 +11,7 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" ) const ( @@ -34,24 +35,23 @@ func CheckNonce( } // MustWaitForTxReceipt waits until a broadcasted tx to be mined and return its receipt -// timeout and panic after 30s. func MustWaitForTxReceipt( ctx context.Context, client *ethclient.Client, tx *ethtypes.Transaction, logger infoLogger, - receiptTimeout time.Duration, + timeout time.Duration, ) *ethtypes.Receipt { - timeout := DefaultReceiptTimeout - if receiptTimeout != 0 { - timeout = receiptTimeout + if timeout == 0 { + timeout = DefaultReceiptTimeout } + t := TestingFromContext(ctx) + start := time.Now() for i := 0; ; i++ { - if time.Since(start) > timeout { - panic("waiting tx receipt timeout") - } + require.False(t, time.Since(start) > timeout, "waiting tx receipt timeout") + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) if err != nil { if !errors.Is(err, ethereum.NotFound) && i%10 == 0 { diff --git a/e2e/utils/require.go b/e2e/utils/require.go new file mode 100644 index 0000000000..ffedb62e59 --- /dev/null +++ b/e2e/utils/require.go @@ -0,0 +1,47 @@ +package utils + +import ( + "fmt" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" + + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +// RequireCCTXStatus checks if the cctx status is equal to the expected status +func RequireCCTXStatus( + t require.TestingT, + cctx *crosschaintypes.CrossChainTx, + expected crosschaintypes.CctxStatus, + msgAndArgs ...any, +) { + msg := fmt.Sprintf("cctx status is not %q", expected.String()) + + require.NotNil(t, cctx.CctxStatus) + require.Equal(t, expected, cctx.CctxStatus.Status, msg+errSuffix(msgAndArgs...)) +} + +// RequireTxSuccessful checks if the receipt status is successful. +// Currently, it accepts eth receipt, but we can make this more generic by using type assertion. +func RequireTxSuccessful(t require.TestingT, receipt *ethtypes.Receipt, msgAndArgs ...any) { + msg := "receipt status is not successful" + require.Equal(t, ethtypes.ReceiptStatusSuccessful, receipt.Status, msg+errSuffix(msgAndArgs...)) +} + +// RequiredTxFailed checks if the receipt status is failed. +// Currently, it accepts eth receipt, but we can make this more generic by using type assertion. +func RequiredTxFailed(t require.TestingT, receipt *ethtypes.Receipt, msgAndArgs ...any) { + msg := "receipt status is not successful" + require.Equal(t, ethtypes.ReceiptStatusFailed, receipt.Status, msg+errSuffix(msgAndArgs...)) +} + +func errSuffix(msgAndArgs ...any) string { + if len(msgAndArgs) == 0 { + return "" + } + + template := "; " + msgAndArgs[0].(string) + + return fmt.Sprintf(template, msgAndArgs[1:]) +} diff --git a/e2e/utils/utils.go b/e2e/utils/utils.go index bfa3d509b3..5bc451c606 100644 --- a/e2e/utils/utils.go +++ b/e2e/utils/utils.go @@ -1,10 +1,12 @@ package utils import ( + "context" "encoding/hex" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" + "github.com/stretchr/testify/require" ) // ScriptPKToAddress is a hex string for P2WPKH script @@ -26,3 +28,20 @@ type infoLogger interface { type NoopLogger struct{} func (nl NoopLogger) Info(_ string, _ ...interface{}) {} + +type testingKey struct{} + +// WithTesting allows to store a testing.T instance in the context +func WithTesting(ctx context.Context, t require.TestingT) context.Context { + return context.WithValue(ctx, testingKey{}, t) +} + +// TestingFromContext extracts require.TestingT from the context or panics. +func TestingFromContext(ctx context.Context) require.TestingT { + t, ok := ctx.Value(testingKey{}).(require.TestingT) + if !ok { + panic("context missing require.TestingT key") + } + + return t +} diff --git a/e2e/utils/zetacore.go b/e2e/utils/zetacore.go index a641ea9518..cbba05de75 100644 --- a/e2e/utils/zetacore.go +++ b/e2e/utils/zetacore.go @@ -2,11 +2,10 @@ package utils import ( "context" - "fmt" "time" rpchttp "github.com/cometbft/cometbft/rpc/client/http" - coretypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/pkg/errors" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -26,14 +25,14 @@ const ( func WaitCctxMinedByInboundHash( ctx context.Context, inboundHash string, - cctxClient crosschaintypes.QueryClient, + client crosschaintypes.QueryClient, logger infoLogger, - cctxTimeout time.Duration, + timeout time.Duration, ) *crosschaintypes.CrossChainTx { - cctxs := WaitCctxsMinedByInboundHash(ctx, inboundHash, cctxClient, 1, logger, cctxTimeout) - if len(cctxs) == 0 { - panic(fmt.Sprintf("cctx not found, inboundHash: %s", inboundHash)) - } + t := TestingFromContext(ctx) + cctxs := WaitCctxsMinedByInboundHash(ctx, inboundHash, client, 1, logger, timeout) + require.NotEmpty(t, cctxs, "cctx not found, inboundHash: %s", inboundHash) + return cctxs[len(cctxs)-1] } @@ -41,41 +40,35 @@ func WaitCctxMinedByInboundHash( func WaitCctxsMinedByInboundHash( ctx context.Context, inboundHash string, - cctxClient crosschaintypes.QueryClient, + client crosschaintypes.QueryClient, cctxsCount int, logger infoLogger, - cctxTimeout time.Duration, + timeout time.Duration, ) []*crosschaintypes.CrossChainTx { - startTime := time.Now() - - timeout := DefaultCctxTimeout - if cctxTimeout != 0 { - timeout = cctxTimeout + if timeout == 0 { + timeout = DefaultCctxTimeout } + t := TestingFromContext(ctx) + + startTime := time.Now() + in := &crosschaintypes.QueryInboundHashToCctxDataRequest{InboundHash: inboundHash} + // fetch cctxs by inboundHash for i := 0; ; i++ { // declare cctxs here so we can print the last fetched one if we reach timeout var cctxs []*crosschaintypes.CrossChainTx - if time.Since(startTime) > timeout { - cctxMessage := "" - if len(cctxs) > 0 { - cctxMessage = fmt.Sprintf(", last cctx: %v", cctxs[0].String()) - } + timedOut := time.Since(startTime) > timeout + require.False(t, timedOut, "waiting cctx timeout, cctx not mined, inbound hash: %s", inboundHash) - panic(fmt.Sprintf("waiting cctx timeout, cctx not mined, inboundHash: %s%s", inboundHash, cctxMessage)) - } time.Sleep(1 * time.Second) // We use InTxHashToCctxData instead of InboundTrackerAllByChain to able to run these tests with the previous version // for the update tests // TODO: replace with InboundHashToCctxData once removed // https://github.com/zeta-chain/node/issues/2200 - res, err := cctxClient.InTxHashToCctxData(ctx, &crosschaintypes.QueryInboundHashToCctxDataRequest{ - InboundHash: inboundHash, - }) - + res, err := client.InTxHashToCctxData(ctx, in) if err != nil { // prevent spamming logs if i%10 == 0 { @@ -126,30 +119,27 @@ func WaitCctxsMinedByInboundHash( func WaitCCTXMinedByIndex( ctx context.Context, cctxIndex string, - cctxClient crosschaintypes.QueryClient, + client crosschaintypes.QueryClient, logger infoLogger, - cctxTimeout time.Duration, + timeout time.Duration, ) *crosschaintypes.CrossChainTx { - startTime := time.Now() - - timeout := DefaultCctxTimeout - if cctxTimeout != 0 { - timeout = cctxTimeout + if timeout == 0 { + timeout = DefaultCctxTimeout } + t := TestingFromContext(ctx) + startTime := time.Now() + in := &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex} + for i := 0; ; i++ { - if time.Since(startTime) > timeout { - panic(fmt.Sprintf( - "waiting cctx timeout, cctx not mined, cctx: %s", - cctxIndex, - )) + require.False(t, time.Since(startTime) > timeout, "waiting cctx timeout, cctx not mined, cctx: %s", cctxIndex) + + if i > 0 { + time.Sleep(1 * time.Second) } - time.Sleep(1 * time.Second) // fetch cctx by index - res, err := cctxClient.Cctx(ctx, &crosschaintypes.QueryGetCctxRequest{ - Index: cctxIndex, - }) + res, err := client.Cctx(ctx, in) if err != nil { // prevent spamming logs if i%10 == 0 { @@ -157,6 +147,7 @@ func WaitCCTXMinedByIndex( } continue } + cctx := res.CrossChainTx if !IsTerminalStatus(cctx.CctxStatus.Status) { // prevent spamming logs @@ -259,26 +250,32 @@ func IsTerminalStatus(status crosschaintypes.CctxStatus) bool { // WaitForBlockHeight waits until the block height reaches the given height func WaitForBlockHeight( ctx context.Context, - height int64, + desiredHeight int64, rpcURL string, logger infoLogger, -) { +) error { // initialize rpc and check status rpc, err := rpchttp.New(rpcURL, "/websocket") if err != nil { - panic(err) + return errors.Wrap(err, "unable to create rpc client") } - status := &coretypes.ResultStatus{} - for i := 0; status.SyncInfo.LatestBlockHeight < height; i++ { - status, err = rpc.Status(ctx) + + var currentHeight int64 + for i := 0; currentHeight < desiredHeight; i++ { + s, err := rpc.Status(ctx) if err != nil { - panic(err) + return errors.Wrap(err, "unable to get status") } + + currentHeight = s.SyncInfo.LatestBlockHeight + time.Sleep(1 * time.Second) // prevent spamming logs if i%10 == 0 { - logger.Info("waiting for block: %d, current height: %d\n", height, status.SyncInfo.LatestBlockHeight) + logger.Info("waiting for block: %d, current height: %d\n", desiredHeight, currentHeight) } } + + return nil } diff --git a/pkg/chains/address_taproot.go b/pkg/chains/address_taproot.go index 1d927e2f9d..4ff270da7d 100644 --- a/pkg/chains/address_taproot.go +++ b/pkg/chains/address_taproot.go @@ -29,7 +29,6 @@ var _ btcutil.Address = &AddressTaproot{} // NewAddressTaproot returns a new AddressTaproot. func NewAddressTaproot(witnessProg []byte, net *chaincfg.Params) (*AddressTaproot, error) { - return newAddressTaproot(net.Bech32HRPSegwit, witnessProg) } diff --git a/pkg/proofs/ethereum/proof.go b/pkg/proofs/ethereum/proof.go index 6d457bc444..b09919f971 100644 --- a/pkg/proofs/ethereum/proof.go +++ b/pkg/proofs/ethereum/proof.go @@ -75,7 +75,6 @@ func (m *Proof) Delete(key []byte) error { func (m *Proof) Has(key []byte) (bool, error) { for i := 0; i < len(m.Keys); i++ { if bytes.Equal(m.Keys[i], key) { - return true, nil } } diff --git a/scripts/fmt-golines.sh b/scripts/fmt-golines.sh deleted file mode 100644 index a24b264d81..0000000000 --- a/scripts/fmt-golines.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Install golines -go install github.com/segmentio/golines@v0.12.2 - -# Run golines in Cosmos modules and ZetaClient codebase -find . -type f -name '*.go' -exec golines -w --max-len=120 {} + > /dev/null 2>&1 - -# Print a message to indicate completion -echo "Go source code lines formatted." \ No newline at end of file diff --git a/scripts/fmt-imports.sh b/scripts/fmt-imports.sh deleted file mode 100644 index 6e9df43948..0000000000 --- a/scripts/fmt-imports.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Install goimports-revise -go install github.com/incu6us/goimports-reviser/v3@v3.6.4 - -# Run goimports-revise on all Go files -find . -name '*.go' -exec goimports-reviser -project-name github.com/zeta-chain/zetacore -file-path {} \; > /dev/null 2>&1 - -# Print a message to indicate completion -echo "Go imports formatted." \ No newline at end of file diff --git a/scripts/fmt.sh b/scripts/fmt.sh new file mode 100755 index 0000000000..7d6ef5eb9f --- /dev/null +++ b/scripts/fmt.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Exit on any error +set -e + +if ! command -v golangci-lint &> /dev/null +then + echo "golangci-lint is not found, installing..." + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1 +fi + +if ! command -v golines &> /dev/null +then + echo "golines could not be found, installing..." + go install github.com/segmentio/golines@v0.12.2 +fi + +# Fix long lines +echo "Fixing long lines..." +golines -w --max-len=120 --ignore-generated --ignored-dirs=".git" --base-formatter="gofmt" . + +# Gofmt, fix & order imports, remove whitespaces +echo "Formatting code..." +golangci-lint run --enable-only 'gci' --enable-only 'gofmt' --enable-only 'whitespace' --fix + +echo "Code is formatted" diff --git a/testutil/helpers.go b/testutil/helpers.go new file mode 100644 index 0000000000..dc49a0b024 --- /dev/null +++ b/testutil/helpers.go @@ -0,0 +1,38 @@ +package testutil + +import ( + "fmt" + "os" + "strings" + + "github.com/stretchr/testify/assert" +) + +const helpersFile = "testutil/helpers.go" + +// Must a helper that terminates the program if the error is not nil. +func Must[T any](v T, err error) T { + NoError(err) + return v +} + +// NoError terminates the program if the error is not nil. +func NoError(err error) { + if err != nil { + exit(err) + } +} + +func exit(err error) { + fmt.Printf("Unable to continue execution: %s.\nStacktrace:\n", err) + + for _, line := range assert.CallerInfo() { + if strings.Contains(line, helpersFile) { + continue + } + + fmt.Println(" ", line) + } + + os.Exit(1) +} diff --git a/testutil/keeper/crosschain.go b/testutil/keeper/crosschain.go index aec1ac7838..d2b1bc1d5b 100644 --- a/testutil/keeper/crosschain.go +++ b/testutil/keeper/crosschain.go @@ -293,7 +293,6 @@ func MockGetRevertGasLimitForERC20( }, true).Once() m.On("QueryGasLimit", mock.Anything, mock.Anything). Return(big.NewInt(returnVal), nil).Once() - } func MockPayGasAndUpdateCCTX( diff --git a/testutil/network/genesis_state.go b/testutil/network/genesis_state.go index 18f464ccb7..7f0bb2003c 100644 --- a/testutil/network/genesis_state.go +++ b/testutil/network/genesis_state.go @@ -28,7 +28,6 @@ func SetupZetaGenesisState( observerList []string, setupChainNonces bool, ) { - // Cross-chain genesis state var crossChainGenesis types.GenesisState require.NoError(t, codec.UnmarshalJSON(genesisState[types.ModuleName], &crossChainGenesis)) diff --git a/testutil/sample/crosschain.go b/testutil/sample/crosschain.go index 7fc6678580..38d490af62 100644 --- a/testutil/sample/crosschain.go +++ b/testutil/sample/crosschain.go @@ -308,7 +308,6 @@ func GetValidZrc20WithdrawToETH(t *testing.T) (receipt ethtypes.Receipt) { err := json.Unmarshal([]byte(block), &receipt) require.NoError(t, err) return - } // receiver is bc1qysd4sp9q8my59ul9wsf5rvs9p387hf8vfwatzu diff --git a/testutil/sample/lightclient.go b/testutil/sample/lightclient.go index 70aa55b51a..bbb0fc1d9b 100644 --- a/testutil/sample/lightclient.go +++ b/testutil/sample/lightclient.go @@ -49,7 +49,6 @@ func HeaderSupportedChains() []lightclienttypes.HeaderSupportedChain { func BlockHeaderVerification() lightclienttypes.BlockHeaderVerification { return lightclienttypes.BlockHeaderVerification{HeaderSupportedChains: HeaderSupportedChains()} - } // Proof generates a proof and block header diff --git a/testutil/sample/os.go b/testutil/sample/os.go new file mode 100644 index 0000000000..b6519adf69 --- /dev/null +++ b/testutil/sample/os.go @@ -0,0 +1,15 @@ +package sample + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +// create a temporary directory for testing +func CreateTempDir(t *testing.T) string { + tempPath, err := os.MkdirTemp("", "tempdir-") + require.NoError(t, err) + return tempPath +} diff --git a/x/authority/client/cli/tx_add_authorization.go b/x/authority/client/cli/tx_add_authorization.go index 5658d24e91..d1329801a3 100644 --- a/x/authority/client/cli/tx_add_authorization.go +++ b/x/authority/client/cli/tx_add_authorization.go @@ -57,5 +57,4 @@ func GetPolicyType(policyTypeString string) (types.PolicyType, error) { default: return types.PolicyType_groupEmpty, fmt.Errorf("invalid policy type value: %d", policyType) } - } diff --git a/x/crosschain/client/cli/cli_tss.go b/x/crosschain/client/cli/cli_tss.go index c24733431f..f1391b9658 100644 --- a/x/crosschain/client/cli/cli_tss.go +++ b/x/crosschain/client/cli/cli_tss.go @@ -19,7 +19,6 @@ func CmdUpdateTss() *cobra.Command { Short: "Create a new TSSVoter", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - argsPubkey, err := cast.ToStringE(args[0]) if err != nil { return err @@ -45,7 +44,6 @@ func CmdMigrateTssFunds() *cobra.Command { Short: "Migrate TSS funds to the latest TSS address", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - argsChainID, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return err diff --git a/x/crosschain/client/cli/cli_zeta_height.go b/x/crosschain/client/cli/cli_zeta_height.go index a2b0f1ea51..7d1f96c8ee 100644 --- a/x/crosschain/client/cli/cli_zeta_height.go +++ b/x/crosschain/client/cli/cli_zeta_height.go @@ -14,7 +14,6 @@ func CmdLastZetaHeight() *cobra.Command { Short: "Query last Zeta Height", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/crosschain/client/querytests/suite.go b/x/crosschain/client/querytests/suite.go index ca42b9b4ec..d9354b6d18 100644 --- a/x/crosschain/client/querytests/suite.go +++ b/x/crosschain/client/querytests/suite.go @@ -52,7 +52,6 @@ func (s *CliTestSuite) SetupSuite() { s.network = net _, err = s.network.WaitForHeight(1) s.Require().NoError(err) - } func (s *CliTestSuite) TearDownSuite() { diff --git a/x/crosschain/keeper/events.go b/x/crosschain/keeper/events.go index 1bff85d750..c503835f14 100644 --- a/x/crosschain/keeper/events.go +++ b/x/crosschain/keeper/events.go @@ -56,7 +56,6 @@ func EmitZetaWithdrawCreated(ctx sdk.Context, cctx types.CrossChainTx) { if err != nil { ctx.Logger().Error("Error emitting ZetaWithdrawCreated :", err) } - } func EmitOutboundSuccess(ctx sdk.Context, valueReceived string, oldStatus string, newStatus string, cctxIndex string) { @@ -70,7 +69,6 @@ func EmitOutboundSuccess(ctx sdk.Context, valueReceived string, oldStatus string if err != nil { ctx.Logger().Error("Error emitting MsgVoteOutbound :", err) } - } func EmitOutboundFailure(ctx sdk.Context, valueReceived string, oldStatus string, newStatus string, cctxIndex string) { diff --git a/x/crosschain/keeper/evm_hooks.go b/x/crosschain/keeper/evm_hooks.go index dbc2d2dbb1..2fc6310800 100644 --- a/x/crosschain/keeper/evm_hooks.go +++ b/x/crosschain/keeper/evm_hooks.go @@ -21,6 +21,7 @@ import ( "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/pkg/constant" "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" @@ -286,15 +287,20 @@ func ValidateZrc20WithdrawEvent(event *zrc20.ZRC20Withdrawal, chainID int64) err // The event was parsed; that means the user has deposited tokens to the contract. if chains.IsBitcoinChain(chainID) { - if event.Value.Cmp(big.NewInt(0)) <= 0 { - return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid amount %s", event.Value.String()) + if event.Value.Cmp(big.NewInt(constant.BTCWithdrawalDustAmount)) < 0 { + return errorsmod.Wrapf( + types.ErrInvalidWithdrawalAmount, + "withdraw amount %s is less than minimum amount %d", + event.Value.String(), + constant.BTCWithdrawalDustAmount, + ) } addr, err := chains.DecodeBtcAddress(string(event.To), chainID) if err != nil { - return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s: %s", event.To, err) + return errorsmod.Wrapf(types.ErrInvalidAddress, "invalid address %s", string(event.To)) } if !chains.IsBtcAddressSupported(addr) { - return fmt.Errorf("ParseZRC20WithdrawalEvent: unsupported address %s", string(event.To)) + return errorsmod.Wrapf(types.ErrInvalidAddress, "unsupported address %s", string(event.To)) } } return nil diff --git a/x/crosschain/keeper/evm_hooks_test.go b/x/crosschain/keeper/evm_hooks_test.go index bc67f34a99..20b1c87e47 100644 --- a/x/crosschain/keeper/evm_hooks_test.go +++ b/x/crosschain/keeper/evm_hooks_test.go @@ -15,6 +15,7 @@ import ( "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/constant" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper" @@ -164,14 +165,21 @@ func TestValidateZrc20WithdrawEvent(t *testing.T) { require.NoError(t, err) }) - t.Run("unable to validate a event with an invalid amount", func(t *testing.T) { + t.Run("unable to validate a btc withdrawal event with an invalid amount", func(t *testing.T) { btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent( *sample.GetValidZRC20WithdrawToBTC(t).Logs[3], ) require.NoError(t, err) - btcMainNetWithdrawalEvent.Value = big.NewInt(0) + + // 1000 satoshis is the minimum amount that can be withdrawn + btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount) err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) - require.ErrorContains(t, err, "ParseZRC20WithdrawalEvent: invalid amount") + require.NoError(t, err) + + // 999 satoshis cannot be withdrawn + btcMainNetWithdrawalEvent.Value = big.NewInt(constant.BTCWithdrawalDustAmount - 1) + err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, chains.BitcoinMainnet.ChainId) + require.ErrorContains(t, err, "less than minimum amount") }) t.Run("unable to validate a event with an invalid chain ID", func(t *testing.T) { @@ -822,7 +830,7 @@ func TestKeeper_ProcessLogs(t *testing.T) { } err := k.ProcessLogs(ctx, block.Logs, sample.EthAddress(), "") - require.ErrorContains(t, err, "ParseZRC20WithdrawalEvent: invalid address") + require.ErrorContains(t, err, "invalid address") cctxList := k.GetAllCrossChainTx(ctx) require.Len(t, cctxList, 0) }) diff --git a/x/crosschain/keeper/msg_server_refund_aborted_tx.go b/x/crosschain/keeper/msg_server_refund_aborted_tx.go index 1efd3227ec..201b507af6 100644 --- a/x/crosschain/keeper/msg_server_refund_aborted_tx.go +++ b/x/crosschain/keeper/msg_server_refund_aborted_tx.go @@ -22,7 +22,6 @@ func (k msgServer) RefundAbortedCCTX( goCtx context.Context, msg *types.MsgRefundAbortedCCTX, ) (*types.MsgRefundAbortedCCTXResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) // check if authorized @@ -99,5 +98,4 @@ func GetRefundAddress(refundAddress string) (ethcommon.Address, error) { return ethcommon.Address{}, errorsmod.Wrap(types.ErrInvalidAddress, "invalid refund address") } return ethRefundAddress, nil - } diff --git a/x/crosschain/keeper/msg_server_update_tss.go b/x/crosschain/keeper/msg_server_update_tss.go index 672d64e462..56052b6671 100644 --- a/x/crosschain/keeper/msg_server_update_tss.go +++ b/x/crosschain/keeper/msg_server_update_tss.go @@ -60,7 +60,6 @@ func (k msgServer) UpdateTssAddress( migratorTx.CctxStatus.Status.String(), ) } - } k.GetObserverKeeper().SetTssAndUpdateNonce(ctx, tss) diff --git a/x/crosschain/migrations/v2/migrate.go b/x/crosschain/migrations/v2/migrate.go index 67f6ae709e..4fad2501bb 100644 --- a/x/crosschain/migrations/v2/migrate.go +++ b/x/crosschain/migrations/v2/migrate.go @@ -19,7 +19,6 @@ func MigrateStore( crossChainStoreKey storetypes.StoreKey, cdc codec.BinaryCodec, ) error { - // Using New Types from observer module as the structure is the same var nodeAccounts []observerTypes.NodeAccount var crosschainFlags observerTypes.CrosschainFlags diff --git a/x/crosschain/migrations/v3/migrate.go b/x/crosschain/migrations/v3/migrate.go index cbe11eef98..a6ec4f293b 100644 --- a/x/crosschain/migrations/v3/migrate.go +++ b/x/crosschain/migrations/v3/migrate.go @@ -19,7 +19,6 @@ func MigrateStore( crossChainStoreKey storetypes.StoreKey, cdc codec.BinaryCodec, ) error { - // Fetch existing TSS existingTss := observertypes.TSS{} store := prefix.NewStore(ctx.KVStore(crossChainStoreKey), types.KeyPrefix(observertypes.TSSKey)) diff --git a/x/crosschain/migrations/v4/migrate.go b/x/crosschain/migrations/v4/migrate.go index 0be2ca2f08..367e9c54eb 100644 --- a/x/crosschain/migrations/v4/migrate.go +++ b/x/crosschain/migrations/v4/migrate.go @@ -130,7 +130,6 @@ func MoveNonceToObserverModule( for _, n := range nonceToCcTx { observerKeeper.SetNonceToCctx(ctx, n) } - } func MoveTssToObserverModule(ctx sdk.Context, diff --git a/x/crosschain/migrations/v5/migrate.go b/x/crosschain/migrations/v5/migrate.go index 58d33629da..fcb42dc4d0 100644 --- a/x/crosschain/migrations/v5/migrate.go +++ b/x/crosschain/migrations/v5/migrate.go @@ -94,7 +94,6 @@ func SetZetaAccounting( abortedAmountZeta := sdkmath.ZeroUint() for _, cctx := range ccctxList { if cctx.CctxStatus.Status == types.CctxStatus_Aborted { - switch cctx.InboundParams.CoinType { case coin.CoinType_ERC20: { @@ -124,7 +123,6 @@ func SetZetaAccounting( abortedValue := GetAbortedAmount(cctx) abortedAmountZeta = abortedAmountZeta.Add(abortedValue) cctx.CctxStatus.IsAbortRefunded = false - } case coin.CoinType_Gas: { @@ -134,7 +132,6 @@ func SetZetaAccounting( } crosschainKeeper.SetCrossChainTx(ctx, cctx) } - } crosschainKeeper.SetZetaAccounting(ctx, types.ZetaAccounting{AbortedZetaAmount: abortedAmountZeta}) diff --git a/x/crosschain/module.go b/x/crosschain/module.go index 01bb84fc82..59f6bdfb11 100644 --- a/x/crosschain/module.go +++ b/x/crosschain/module.go @@ -136,7 +136,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 4, m.Migrate4to5); err != nil { panic(err) } - } // RegisterInvariants registers the crosschain module's invariants. diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go index 232bf229db..6f430e5e1a 100644 --- a/x/crosschain/types/errors.go +++ b/x/crosschain/types/errors.go @@ -49,4 +49,5 @@ var ( ErrInvalidRateLimiterFlags = errorsmod.Register(ModuleName, 1152, "invalid rate limiter flags") ErrMaxTxOutTrackerHashesReached = errorsmod.Register(ModuleName, 1153, "max tx out tracker hashes reached") ErrInitiatitingOutbound = errorsmod.Register(ModuleName, 1154, "cannot initiate outbound") + ErrInvalidWithdrawalAmount = errorsmod.Register(ModuleName, 1155, "invalid withdrawal amount") ) diff --git a/x/crosschain/types/status.go b/x/crosschain/types/status.go index ded81edeec..320209ae78 100644 --- a/x/crosschain/types/status.go +++ b/x/crosschain/types/status.go @@ -31,7 +31,6 @@ func (m *Status) ChangeStatus(newStatus CctxStatus, msg string) { return } m.Status = newStatus - } //nolint:typecheck func (m *Status) ValidateTransition(newStatus CctxStatus) bool { diff --git a/x/emissions/client/cli/query_get_emmisons_factors.go b/x/emissions/client/cli/query_get_emmisons_factors.go index c98ec7c6af..ef19623975 100644 --- a/x/emissions/client/cli/query_get_emmisons_factors.go +++ b/x/emissions/client/cli/query_get_emmisons_factors.go @@ -14,7 +14,6 @@ func CmdGetEmmisonsFactors() *cobra.Command { Short: "Query GetEmmisonsFactors", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/emissions/client/cli/query_list_balances.go b/x/emissions/client/cli/query_list_balances.go index 3e40965d87..d16b0191dc 100644 --- a/x/emissions/client/cli/query_list_balances.go +++ b/x/emissions/client/cli/query_list_balances.go @@ -14,7 +14,6 @@ func CmdListPoolAddresses() *cobra.Command { Short: "Query list-pool-addresses", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/fungible/client/cli/tx_update_contract_bytecode.go b/x/fungible/client/cli/tx_update_contract_bytecode.go index 334cd12a68..2b2077792c 100644 --- a/x/fungible/client/cli/tx_update_contract_bytecode.go +++ b/x/fungible/client/cli/tx_update_contract_bytecode.go @@ -15,7 +15,6 @@ func CmdUpdateContractBytecode() *cobra.Command { Short: "Broadcast message UpdateContractBytecode", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/fungible/genesis.go b/x/fungible/genesis.go index ba8a3d0153..be5d6f7555 100644 --- a/x/fungible/genesis.go +++ b/x/fungible/genesis.go @@ -18,7 +18,6 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) if genState.SystemContract != nil { k.SetSystemContract(ctx, *genState.SystemContract) } - } // ExportGenesis returns the fungible module's exported genesis. diff --git a/x/lightclient/client/cli/tx_disable_verification_flags.go b/x/lightclient/client/cli/tx_disable_verification_flags.go index 4d86dee552..41ba1203a6 100644 --- a/x/lightclient/client/cli/tx_disable_verification_flags.go +++ b/x/lightclient/client/cli/tx_disable_verification_flags.go @@ -24,7 +24,6 @@ func CmdDisableVerificationFlags() *cobra.Command { `, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/lightclient/client/cli/tx_enable_verification_flags.go b/x/lightclient/client/cli/tx_enable_verification_flags.go index cf896fd2be..d8866c7400 100644 --- a/x/lightclient/client/cli/tx_enable_verification_flags.go +++ b/x/lightclient/client/cli/tx_enable_verification_flags.go @@ -24,7 +24,6 @@ func CmdEnableVerificationFlags() *cobra.Command { `, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/lightclient/keeper/grpc_query_header_enabled_chains.go b/x/lightclient/keeper/grpc_query_header_enabled_chains.go index 8a9700cc03..7408923ad8 100644 --- a/x/lightclient/keeper/grpc_query_header_enabled_chains.go +++ b/x/lightclient/keeper/grpc_query_header_enabled_chains.go @@ -51,5 +51,4 @@ func (k Keeper) HeaderEnabledChains( } return &types.QueryHeaderEnabledChainsResponse{HeaderEnabledChains: val.GetHeaderEnabledChains()}, nil - } diff --git a/x/lightclient/types/message_disable_verification_flags.go b/x/lightclient/types/message_disable_verification_flags.go index e051a7d4b7..5ee2964aa7 100644 --- a/x/lightclient/types/message_disable_verification_flags.go +++ b/x/lightclient/types/message_disable_verification_flags.go @@ -19,7 +19,6 @@ func NewMsgDisableHeaderVerification(creator string, chainIDs []int64) *MsgDisab Creator: creator, ChainIdList: chainIDs, } - } func (msg *MsgDisableHeaderVerification) Route() string { diff --git a/x/observer/client/cli/query_blame.go b/x/observer/client/cli/query_blame.go index ded997d35c..9d173f0a00 100644 --- a/x/observer/client/cli/query_blame.go +++ b/x/observer/client/cli/query_blame.go @@ -49,7 +49,6 @@ func CmdGetAllBlameRecords() *cobra.Command { Short: "Query AllBlameRecords", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/query_chain_params.go b/x/observer/client/cli/query_chain_params.go index b4126b5c76..3652dbf411 100644 --- a/x/observer/client/cli/query_chain_params.go +++ b/x/observer/client/cli/query_chain_params.go @@ -48,7 +48,6 @@ func CmdGetChainParams() *cobra.Command { Short: "Query GetChainParams", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/query_get_tss_address.go b/x/observer/client/cli/query_get_tss_address.go index f663ca43df..8e9b92d8bb 100644 --- a/x/observer/client/cli/query_get_tss_address.go +++ b/x/observer/client/cli/query_get_tss_address.go @@ -16,7 +16,6 @@ func CmdGetTssAddress() *cobra.Command { Short: "Query current tss address", Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err @@ -51,7 +50,6 @@ func CmdGetTssAddressByFinalizedZetaHeight() *cobra.Command { Short: "Query tss address by finalized zeta height (for historical tss addresses)", Args: cobra.MaximumNArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/query_observers.go b/x/observer/client/cli/query_observers.go index 6bdc34616c..721a0b12a6 100644 --- a/x/observer/client/cli/query_observers.go +++ b/x/observer/client/cli/query_observers.go @@ -14,7 +14,6 @@ func CmdObserverSet() *cobra.Command { Short: "Query observer set", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/query_show_observer_count.go b/x/observer/client/cli/query_show_observer_count.go index 43c7feb7a6..0f5f6039b0 100644 --- a/x/observer/client/cli/query_show_observer_count.go +++ b/x/observer/client/cli/query_show_observer_count.go @@ -14,7 +14,6 @@ func CmdShowObserverCount() *cobra.Command { Short: "Query show-observer-count", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_add_observer.go b/x/observer/client/cli/tx_add_observer.go index 3c18fbcca5..b55606c1d1 100644 --- a/x/observer/client/cli/tx_add_observer.go +++ b/x/observer/client/cli/tx_add_observer.go @@ -18,7 +18,6 @@ func CmdAddObserver() *cobra.Command { Short: "Broadcast message add-observer", Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_disable_cctx_flags.go b/x/observer/client/cli/tx_disable_cctx_flags.go index 53cdf923bf..be88aada31 100644 --- a/x/observer/client/cli/tx_disable_cctx_flags.go +++ b/x/observer/client/cli/tx_disable_cctx_flags.go @@ -17,7 +17,6 @@ func CmdDisableCCTX() *cobra.Command { Short: "Disable inbound and outbound for CCTX", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_enable_cctx_flags.go b/x/observer/client/cli/tx_enable_cctx_flags.go index c21016e258..d4371118bd 100644 --- a/x/observer/client/cli/tx_enable_cctx_flags.go +++ b/x/observer/client/cli/tx_enable_cctx_flags.go @@ -17,7 +17,6 @@ func CmdEnableCCTX() *cobra.Command { Short: "Enable inbound and outbound for CCTX", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_update_chain_params.go b/x/observer/client/cli/tx_update_chain_params.go index 81e5cac7a1..d677801c6a 100644 --- a/x/observer/client/cli/tx_update_chain_params.go +++ b/x/observer/client/cli/tx_update_chain_params.go @@ -19,7 +19,6 @@ func CmdUpdateChainParams() *cobra.Command { Short: "Broadcast message updateChainParams", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { - argChainParams := args[0] clientCtx, err := client.GetClientTxContext(cmd) diff --git a/x/observer/client/cli/tx_update_gas_price_increase_flags.go b/x/observer/client/cli/tx_update_gas_price_increase_flags.go index e2cc0a5685..5569104bcf 100644 --- a/x/observer/client/cli/tx_update_gas_price_increase_flags.go +++ b/x/observer/client/cli/tx_update_gas_price_increase_flags.go @@ -18,7 +18,6 @@ func CmdUpdateGasPriceIncreaseFlags() *cobra.Command { Short: "Update the gas price increase flags", Args: cobra.ExactArgs(5), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_update_observer.go b/x/observer/client/cli/tx_update_observer.go index abc8c72e51..c04cfa2664 100644 --- a/x/observer/client/cli/tx_update_observer.go +++ b/x/observer/client/cli/tx_update_observer.go @@ -19,7 +19,6 @@ func CmdUpdateObserver() *cobra.Command { Short: "Broadcast message add-observer", Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/observer/client/cli/tx_vote_tss.go b/x/observer/client/cli/tx_vote_tss.go index 088ec36fcf..ce6591c749 100644 --- a/x/observer/client/cli/tx_vote_tss.go +++ b/x/observer/client/cli/tx_vote_tss.go @@ -19,7 +19,6 @@ func CmdVoteTSS() *cobra.Command { Short: "Vote for a new TSS creation", Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error { - argsPubkey, err := cast.ToStringE(args[0]) if err != nil { return err diff --git a/x/observer/client/querytests/suite.go b/x/observer/client/querytests/suite.go index 8fc7063676..c0a0710c5b 100644 --- a/x/observer/client/querytests/suite.go +++ b/x/observer/client/querytests/suite.go @@ -51,7 +51,6 @@ func (s *CliTestSuite) SetupSuite() { s.network = net _, err = s.network.WaitForHeight(1) s.Require().NoError(err) - } func (s *CliTestSuite) TearDownSuite() { diff --git a/x/observer/genesis.go b/x/observer/genesis.go index 9a8a3bcee1..d39a771535 100644 --- a/x/observer/genesis.go +++ b/x/observer/genesis.go @@ -130,7 +130,6 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, elem := range genState.NonceToCctx { k.SetNonceToCctx(ctx, elem) } - } // ExportGenesis returns the observer module's exported genesis. diff --git a/x/observer/keeper/grpc_query_observer.go b/x/observer/keeper/grpc_query_observer.go index 181ba163f8..5ae55ab30a 100644 --- a/x/observer/keeper/grpc_query_observer.go +++ b/x/observer/keeper/grpc_query_observer.go @@ -46,5 +46,4 @@ func (k Keeper) ObserverSet( return &types.QueryObserverSetResponse{ Observers: observerSet.ObserverList, }, nil - } diff --git a/x/observer/keeper/hooks.go b/x/observer/keeper/hooks.go index 7e11cae282..afe6b9eb91 100644 --- a/x/observer/keeper/hooks.go +++ b/x/observer/keeper/hooks.go @@ -37,7 +37,6 @@ func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, } func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) error { - err := h.k.CleanSlashedValidator(ctx, valAddr, fraction) if err != nil { return err diff --git a/x/observer/keeper/keeper.go b/x/observer/keeper/keeper.go index 1019fc1002..1b26fd3af3 100644 --- a/x/observer/keeper/keeper.go +++ b/x/observer/keeper/keeper.go @@ -48,7 +48,6 @@ func NewKeeper( lightclientKeeper: lightclientKeeper, authority: authority, } - } func (k Keeper) GetSlashingKeeper() types.SlashingKeeper { diff --git a/x/observer/keeper/msg_server_vote_tss.go b/x/observer/keeper/msg_server_vote_tss.go index 065bfe68f2..ae40c41444 100644 --- a/x/observer/keeper/msg_server_vote_tss.go +++ b/x/observer/keeper/msg_server_vote_tss.go @@ -51,7 +51,6 @@ func (k msgServer) VoteTSS(goCtx context.Context, msg *types.MsgVoteTSS) (*types index := msg.Digest() ballot, found := k.GetBallot(ctx, index) if !found { - // if ballot does not exist, create a new ballot var voterList []string diff --git a/x/observer/keeper/nonce_to_cctx.go b/x/observer/keeper/nonce_to_cctx.go index 057f4b1b4b..8042a6df28 100644 --- a/x/observer/keeper/nonce_to_cctx.go +++ b/x/observer/keeper/nonce_to_cctx.go @@ -51,9 +51,7 @@ func (k Keeper) GetAllNonceToCctx(ctx sdk.Context) (list []types.NonceToCctx) { if err == nil { list = append(list, val) } - } return - } diff --git a/x/observer/keeper/observer_set.go b/x/observer/keeper/observer_set.go index deeae5395b..c8a22e0e0f 100644 --- a/x/observer/keeper/observer_set.go +++ b/x/observer/keeper/observer_set.go @@ -34,7 +34,6 @@ func (k Keeper) IsAddressPartOfObserverSet(ctx sdk.Context, address string) bool } } return false - } func (k Keeper) AddObserverToSet(ctx sdk.Context, address string) { diff --git a/x/observer/keeper/tss.go b/x/observer/keeper/tss.go index 55915d55d2..1d885a68cf 100644 --- a/x/observer/keeper/tss.go +++ b/x/observer/keeper/tss.go @@ -45,7 +45,6 @@ func (k Keeper) GetHistoricalTssByFinalizedHeight(ctx sdk.Context, finalizedZeta return types.TSS{}, false } return tss, true - } // GetTSS returns the current tss information diff --git a/x/observer/types/ballot.go b/x/observer/types/ballot.go index 2ddab67ec6..6c04963cf9 100644 --- a/x/observer/types/ballot.go +++ b/x/observer/types/ballot.go @@ -62,7 +62,6 @@ func (m Ballot) IsFinalizingVote() (Ballot, bool) { if vote == VoteType_FailureObservation { failure = failure.Add(sdk.OneDec()) } - } if failure.IsPositive() { if failure.Quo(total).GTE(m.BallotThreshold) { diff --git a/x/observer/types/keys.go b/x/observer/types/keys.go index eb05d34142..40b088686c 100644 --- a/x/observer/types/keys.go +++ b/x/observer/types/keys.go @@ -34,7 +34,6 @@ func GetMinObserverDelegation() (sdkmath.Int, bool) { func GetMinObserverDelegationDec() (sdk.Dec, error) { return sdk.NewDecFromStr(MinObserverDelegation) - } func KeyPrefix(p string) []byte { diff --git a/zetaclient/chains/base/logger_test.go b/zetaclient/chains/base/logger_test.go index 07c2859b0e..07c0941f5a 100644 --- a/zetaclient/chains/base/logger_test.go +++ b/zetaclient/chains/base/logger_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/config" ) @@ -23,7 +24,7 @@ func TestInitLogger(t *testing.T) { LogFormat: "json", LogLevel: 1, // zerolog.InfoLevel, ComplianceConfig: config.ComplianceConfig{ - LogPath: createTempDir(t), + LogPath: sample.CreateTempDir(t), }, }, fail: false, @@ -34,7 +35,7 @@ func TestInitLogger(t *testing.T) { LogFormat: "text", LogLevel: 2, // zerolog.WarnLevel, ComplianceConfig: config.ComplianceConfig{ - LogPath: createTempDir(t), + LogPath: sample.CreateTempDir(t), }, }, fail: false, @@ -45,7 +46,7 @@ func TestInitLogger(t *testing.T) { LogFormat: "unknown", LogLevel: 3, // zerolog.ErrorLevel, ComplianceConfig: config.ComplianceConfig{ - LogPath: createTempDir(t), + LogPath: sample.CreateTempDir(t), }, }, fail: false, @@ -57,7 +58,7 @@ func TestInitLogger(t *testing.T) { LogLevel: 4, // zerolog.DebugLevel, LogSampler: true, ComplianceConfig: config.ComplianceConfig{ - LogPath: createTempDir(t), + LogPath: sample.CreateTempDir(t), }, }, }, diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go index 7dd2f18081..6972478190 100644 --- a/zetaclient/chains/base/observer_test.go +++ b/zetaclient/chains/base/observer_test.go @@ -18,13 +18,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" ) -// create a temporary directory for testing -func createTempDir(t *testing.T) string { - tempPath, err := os.MkdirTemp("", "tempdir-") - require.NoError(t, err) - return tempPath -} - // createObserver creates a new observer for testing func createObserver(t *testing.T, dbPath string) *base.Observer { // constructor parameters @@ -62,7 +55,7 @@ func TestNewObserver(t *testing.T) { tss := mocks.NewTSSMainnet() blockCacheSize := base.DefaultBlockCacheSize headersCacheSize := base.DefaultHeadersCacheSize - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) // test cases tests := []struct { @@ -159,7 +152,7 @@ func TestNewObserver(t *testing.T) { } func TestObserverGetterAndSetter(t *testing.T) { - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) t.Run("should be able to update chain", func(t *testing.T) { ob := createObserver(t, dbPath) @@ -258,7 +251,7 @@ func TestObserverGetterAndSetter(t *testing.T) { } func TestOpenDB(t *testing.T) { - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) t.Run("should be able to open db", func(t *testing.T) { @@ -277,7 +270,7 @@ func TestLoadLastBlockScanned(t *testing.T) { t.Run("should be able to load last block scanned", func(t *testing.T) { // create db and write 100 as last block scanned - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) ob.WriteLastBlockScannedToDB(100) @@ -289,7 +282,7 @@ func TestLoadLastBlockScanned(t *testing.T) { }) t.Run("should use latest block if last block scanned not found", func(t *testing.T) { // create empty db - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) // read last block scanned @@ -299,7 +292,7 @@ func TestLoadLastBlockScanned(t *testing.T) { }) t.Run("should overwrite last block scanned if env var is set", func(t *testing.T) { // create db and write 100 as last block scanned - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) ob.WriteLastBlockScannedToDB(100) @@ -322,7 +315,7 @@ func TestLoadLastBlockScanned(t *testing.T) { }) t.Run("should return error on invalid env var", func(t *testing.T) { // create db and write 100 as last block scanned - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) // set invalid env var @@ -338,7 +331,7 @@ func TestLoadLastBlockScanned(t *testing.T) { func TestReadWriteLastBlockScannedToDB(t *testing.T) { t.Run("should be able to write and read last block scanned to db", func(t *testing.T) { // create db and write 100 as last block scanned - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) err := ob.WriteLastBlockScannedToDB(100) require.NoError(t, err) @@ -349,7 +342,7 @@ func TestReadWriteLastBlockScannedToDB(t *testing.T) { }) t.Run("should return error when last block scanned not found in db", func(t *testing.T) { // create empty db - dbPath := createTempDir(t) + dbPath := sample.CreateTempDir(t) ob := createObserver(t, dbPath) lastScannedBlock, err := ob.ReadLastBlockScannedFromDB() diff --git a/zetaclient/chains/base/signer.go b/zetaclient/chains/base/signer.go index 2585218767..a33f116e48 100644 --- a/zetaclient/chains/base/signer.go +++ b/zetaclient/chains/base/signer.go @@ -1,6 +1,8 @@ package base import ( + "sync" + "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/context" @@ -24,6 +26,10 @@ type Signer struct { // logger contains the loggers used by signer logger Logger + + // mu protects fields from concurrent access + // Note: base signer simply provides the mutex. It's the sub-struct's responsibility to use it to be thread-safe + mu *sync.Mutex } // NewSigner creates a new base signer @@ -43,6 +49,7 @@ func NewSigner( Std: logger.Std.With().Int64("chain", chain.ChainId).Str("module", "signer").Logger(), Compliance: logger.Compliance, }, + mu: &sync.Mutex{}, } } @@ -94,3 +101,8 @@ func (s *Signer) WithTelemetryServer(ts *metrics.TelemetryServer) *Signer { func (s *Signer) Logger() *Logger { return &s.logger } + +// Mu returns the mutex for the signer +func (s *Signer) Mu() *sync.Mutex { + return s.mu +} diff --git a/zetaclient/chains/base/signer_test.go b/zetaclient/chains/base/signer_test.go index 960c508d6e..3de1d18d4a 100644 --- a/zetaclient/chains/base/signer_test.go +++ b/zetaclient/chains/base/signer_test.go @@ -71,4 +71,8 @@ func TestSignerGetterAndSetter(t *testing.T) { logger.Std.Info().Msg("print standard log") logger.Compliance.Info().Msg("print compliance log") }) + t.Run("should be able to get mutex", func(t *testing.T) { + signer := createSigner(t) + require.NotNil(t, signer.Mu()) + }) } diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index a17d46883f..47d026c11a 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -328,7 +328,6 @@ func (ob *Observer) refreshPendingNonce() { } func (ob *Observer) getOutboundIDByNonce(nonce uint64, test bool) (string, error) { - // There are 2 types of txids an observer can trust // 1. The ones had been verified and saved by observer self. // 2. The ones had been finalized in zetacore based on majority vote. diff --git a/zetaclient/chains/bitcoin/signer/signer.go b/zetaclient/chains/bitcoin/signer/signer.go index f2d47fd988..d39b8a8f9d 100644 --- a/zetaclient/chains/bitcoin/signer/signer.go +++ b/zetaclient/chains/bitcoin/signer/signer.go @@ -15,7 +15,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" @@ -30,7 +29,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" "github.com/zeta-chain/zetacore/zetaclient/outboundprocessor" - "github.com/zeta-chain/zetacore/zetaclient/tss" ) const ( @@ -45,20 +43,25 @@ var _ interfaces.ChainSigner = &Signer{} // Signer deals with signing BTC transactions and implements the ChainSigner interface type Signer struct { - tssSigner interfaces.TSSSigner - rpcClient interfaces.BTCRPCClient - logger zerolog.Logger - loggerCompliance zerolog.Logger - ts *metrics.TelemetryServer - coreContext *context.ZetacoreContext + // base.Signer implements the base chain signer + base.Signer + + // client is the RPC client to interact with the Bitcoin chain + client interfaces.BTCRPCClient } +// NewSigner creates a new Bitcoin signer func NewSigner( - cfg config.BTCConfig, - tssSigner interfaces.TSSSigner, - logger base.Logger, + chain chains.Chain, + zetacoreContext *context.ZetacoreContext, + tss interfaces.TSSSigner, ts *metrics.TelemetryServer, - coreContext *context.ZetacoreContext) (*Signer, error) { + logger base.Logger, + cfg config.BTCConfig) (*Signer, error) { + // create base signer + baseSigner := base.NewSigner(chain, zetacoreContext, tss, ts, logger) + + // create the bitcoin rpc client using the provided config connCfg := &rpcclient.ConnConfig{ Host: cfg.RPCHost, User: cfg.RPCUsername, @@ -73,12 +76,8 @@ func NewSigner( } return &Signer{ - tssSigner: tssSigner, - rpcClient: client, - logger: logger.Std.With().Str("chain", "BTC").Str("module", "BTCSigner").Logger(), - loggerCompliance: logger.Compliance, - ts: ts, - coreContext: coreContext, + Signer: *baseSigner, + client: client, }, nil } @@ -130,12 +129,12 @@ func (signer *Signer) AddWithdrawTxOutputs( if remainingSats < 0 { return fmt.Errorf("remainder value is negative: %d", remainingSats) } else if remainingSats == nonceMark { - signer.logger.Info().Msgf("adjust remainder value to avoid duplicate nonce-mark: %d", remainingSats) + signer.Logger().Std.Info().Msgf("adjust remainder value to avoid duplicate nonce-mark: %d", remainingSats) remainingSats-- } // 1st output: the nonce-mark btc to TSS self - tssAddrP2WPKH := signer.tssSigner.BTCAddressWitnessPubkeyHash() + tssAddrP2WPKH := signer.TSS().BTCAddressWitnessPubkeyHash() payToSelfScript, err := bitcoin.PayToAddrScript(tssAddrP2WPKH) if err != nil { return err @@ -182,7 +181,10 @@ func (signer *Signer) SignWithdrawTx( // refresh unspent UTXOs and continue with keysign regardless of error err := observer.FetchUTXOs() if err != nil { - signer.logger.Error().Err(err).Msgf("SignWithdrawTx: FetchUTXOs error: nonce %d chain %d", nonce, chain.ChainId) + signer.Logger(). + Std.Error(). + Err(err). + Msgf("SignWithdrawTx: FetchUTXOs error: nonce %d chain %d", nonce, chain.ChainId) } // select N UTXOs to cover the total expense @@ -216,16 +218,16 @@ func (signer *Signer) SignWithdrawTx( return nil, err } if sizeLimit < bitcoin.BtcOutboundBytesWithdrawer { // ZRC20 'withdraw' charged less fee from end user - signer.logger.Info(). + signer.Logger().Std.Info(). Msgf("sizeLimit %d is less than BtcOutboundBytesWithdrawer %d for nonce %d", sizeLimit, txSize, nonce) } if txSize < bitcoin.OutboundBytesMin { // outbound shouldn't be blocked a low sizeLimit - signer.logger.Warn(). + signer.Logger().Std.Warn(). Msgf("txSize %d is less than outboundBytesMin %d; use outboundBytesMin", txSize, bitcoin.OutboundBytesMin) txSize = bitcoin.OutboundBytesMin } if txSize > bitcoin.OutboundBytesMax { // in case of accident - signer.logger.Warn(). + signer.Logger().Std.Warn(). Msgf("txSize %d is greater than outboundBytesMax %d; use outboundBytesMax", txSize, bitcoin.OutboundBytesMax) txSize = bitcoin.OutboundBytesMax } @@ -233,8 +235,10 @@ func (signer *Signer) SignWithdrawTx( // fee calculation // #nosec G701 always in range (checked above) fees := new(big.Int).Mul(big.NewInt(int64(txSize)), gasPrice) - signer.logger.Info().Msgf("bitcoin outbound nonce %d gasPrice %s size %d fees %s consolidated %d utxos of value %v", - nonce, gasPrice.String(), txSize, fees.String(), consolidatedUtxo, consolidatedValue) + signer.Logger(). + Std.Info(). + Msgf("bitcoin outbound nonce %d gasPrice %s size %d fees %s consolidated %d utxos of value %v", + nonce, gasPrice.String(), txSize, fees.String(), consolidatedUtxo, consolidatedValue) // add tx outputs err = signer.AddWithdrawTxOutputs(tx, to, total, amount, nonceMark, fees, cancelTx) @@ -260,11 +264,7 @@ func (signer *Signer) SignWithdrawTx( } } - tssSigner, ok := signer.tssSigner.(*tss.TSS) - if !ok { - return nil, fmt.Errorf("tssSigner is not a TSS") - } - sig65Bs, err := tssSigner.SignBatch(witnessHashes, height, nonce, &chain) + sig65Bs, err := signer.TSS().SignBatch(witnessHashes, height, nonce, chain.ChainId) if err != nil { return nil, fmt.Errorf("SignBatch error: %v", err) } @@ -278,7 +278,7 @@ func (signer *Signer) SignWithdrawTx( S: S, } - pkCompressed := signer.tssSigner.PubKeyCompressedBytes() + pkCompressed := signer.TSS().PubKeyCompressedBytes() hashType := txscript.SigHashAll txWitness := wire.TxWitness{append(sig.Serialize(), byte(hashType)), pkCompressed} tx.TxIn[ix].Witness = txWitness @@ -298,12 +298,12 @@ func (signer *Signer) Broadcast(signedTx *wire.MsgTx) error { str := hex.EncodeToString(outBuff.Bytes()) fmt.Printf("BTCSigner: Transaction Data: %s\n", str) - hash, err := signer.rpcClient.SendRawTransaction(signedTx, true) + hash, err := signer.client.SendRawTransaction(signedTx, true) if err != nil { return err } - signer.logger.Info().Msgf("Broadcasting BTC tx , hash %s ", hash) + signer.Logger().Std.Info().Msgf("Broadcasting BTC tx , hash %s ", hash) return nil } @@ -318,11 +318,11 @@ func (signer *Signer) TryProcessOutbound( defer func() { outboundProcessor.EndTryProcess(outboundID) if err := recover(); err != nil { - signer.logger.Error().Msgf("BTC TryProcessOutbound: %s, caught panic error: %v", cctx.Index, err) + signer.Logger().Std.Error().Msgf("BTC TryProcessOutbound: %s, caught panic error: %v", cctx.Index, err) } }() - logger := signer.logger.With(). + logger := signer.Logger().Std.With(). Str("OutboundID", outboundID). Str("SendHash", cctx.Index). Logger() @@ -341,7 +341,7 @@ func (signer *Signer) TryProcessOutbound( logger.Error().Msgf("chain observer is not a bitcoin observer") return } - flags := signer.coreContext.GetCrossChainFlags() + flags := signer.ZetacoreContext().GetCrossChainFlags() if !flags.IsOutboundEnabled { logger.Info().Msgf("outbound is disabled") return @@ -375,7 +375,7 @@ func (signer *Signer) TryProcessOutbound( amount := float64(params.Amount.Uint64()) / 1e8 // Add 1 satoshi/byte to gasPrice to avoid minRelayTxFee issue - networkInfo, err := signer.rpcClient.GetNetworkInfo() + networkInfo, err := signer.client.GetNetworkInfo() if err != nil { logger.Error().Err(err).Msgf("cannot get bitcoin network info") return @@ -386,7 +386,7 @@ func (signer *Signer) TryProcessOutbound( // compliance check cancelTx := compliance.IsCctxRestricted(cctx) if cancelTx { - compliance.PrintComplianceLog(logger, signer.loggerCompliance, + compliance.PrintComplianceLog(logger, signer.Logger().Compliance, true, chain.ChainId, cctx.Index, cctx.InboundParams.Sender, params.Receiver, "BTC") amount = 0.0 // zero out the amount to cancel the tx } diff --git a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go index 8cc90cf3eb..2506f57059 100644 --- a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go @@ -15,7 +15,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/stretchr/testify/suite" - "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" @@ -147,7 +146,7 @@ func getTSSTX( return "", err } - sig65B, err := tss.Sign(witnessHash, 10, 10, &chains.Chain{}, "") + sig65B, err := tss.Sign(witnessHash, 10, 10, 0, "") R := big.NewInt(0).SetBytes(sig65B[:32]) S := big.NewInt(0).SetBytes(sig65B[32:64]) sig := btcec.Signature{ diff --git a/zetaclient/chains/bitcoin/signer/signer_test.go b/zetaclient/chains/bitcoin/signer/signer_test.go index 74628211a4..e351d4a65c 100644 --- a/zetaclient/chains/bitcoin/signer/signer_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_test.go @@ -21,8 +21,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" "github.com/zeta-chain/zetacore/zetaclient/config" - "github.com/zeta-chain/zetacore/zetaclient/context" - "github.com/zeta-chain/zetacore/zetaclient/metrics" "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" ) @@ -48,13 +46,14 @@ func (s *BTCSignerSuite) SetUpTest(c *C) { tss := &mocks.TSS{ PrivKey: privateKey, } - cfg := config.NewConfig() s.btcSigner, err = NewSigner( - config.BTCConfig{}, + chains.Chain{}, + nil, tss, + nil, base.DefaultLogger(), - &metrics.TelemetryServer{}, - context.NewZetacoreContext(cfg)) + config.BTCConfig{}, + ) c.Assert(err, IsNil) } @@ -231,16 +230,17 @@ func (s *BTCSignerSuite) TestP2WPH(c *C) { func TestAddWithdrawTxOutputs(t *testing.T) { // Create test signer and receiver address signer, err := NewSigner( - config.BTCConfig{}, + chains.Chain{}, + nil, mocks.NewTSSMainnet(), - base.DefaultLogger(), - &metrics.TelemetryServer{}, nil, + base.DefaultLogger(), + config.BTCConfig{}, ) require.NoError(t, err) // tss address and script - tssAddr := signer.tssSigner.BTCAddressWitnessPubkeyHash() + tssAddr := signer.TSS().BTCAddressWitnessPubkeyHash() tssScript, err := bitcoin.PayToAddrScript(tssAddr) require.NoError(t, err) fmt.Printf("tss address: %s", tssAddr.EncodeAddress()) @@ -392,13 +392,13 @@ func TestNewBTCSigner(t *testing.T) { tss := &mocks.TSS{ PrivKey: privateKey, } - cfg := config.NewConfig() btcSigner, err := NewSigner( - config.BTCConfig{}, + chains.Chain{}, + nil, tss, + nil, base.DefaultLogger(), - &metrics.TelemetryServer{}, - context.NewZetacoreContext(cfg)) + config.BTCConfig{}) require.NoError(t, err) require.NotNil(t, btcSigner) } diff --git a/zetaclient/chains/evm/observer/observer.go b/zetaclient/chains/evm/observer/observer.go index 99db258f5a..0b3c02113c 100644 --- a/zetaclient/chains/evm/observer/observer.go +++ b/zetaclient/chains/evm/observer/observer.go @@ -481,7 +481,6 @@ func (ob *Observer) WatchGasPrice() { } func (ob *Observer) PostGasPrice() error { - // GAS PRICE gasPrice, err := ob.evmClient.SuggestGasPrice(context.TODO()) if err != nil { diff --git a/zetaclient/chains/evm/signer/outbound_data.go b/zetaclient/chains/evm/signer/outbound_data.go index d12ecb118c..070c73597e 100644 --- a/zetaclient/chains/evm/signer/outbound_data.go +++ b/zetaclient/chains/evm/signer/outbound_data.go @@ -71,7 +71,6 @@ func (txData *OutboundData) SetupGas( client interfaces.EVMRPCClient, chain *chains.Chain, ) error { - txData.gasLimit = cctx.GetCurrentOutboundParam().GasLimit if txData.gasLimit < MinGasLimit { txData.gasLimit = MinGasLimit diff --git a/zetaclient/chains/evm/signer/signer.go b/zetaclient/chains/evm/signer/signer.go index d49895e2a3..4fa29a015b 100644 --- a/zetaclient/chains/evm/signer/signer.go +++ b/zetaclient/chains/evm/signer/signer.go @@ -5,10 +5,8 @@ import ( "encoding/hex" "fmt" "math/big" - "math/rand" "strconv" "strings" - "sync" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -48,39 +46,54 @@ var ( // Signer deals with the signing EVM transactions and implements the ChainSigner interface type Signer struct { - client interfaces.EVMRPCClient - chain *chains.Chain - tssSigner interfaces.TSSSigner - ethSigner ethtypes.Signer - logger base.Logger - ts *metrics.TelemetryServer - coreContext *clientcontext.ZetacoreContext - - // mu protects below fields from concurrent access - mu *sync.Mutex - zetaConnectorABI abi.ABI - erc20CustodyABI abi.ABI - zetaConnectorAddress ethcommon.Address - er20CustodyAddress ethcommon.Address + // base.Signer implements the base chain signer + base.Signer + + // client is the EVM RPC client to interact with the EVM chain + client interfaces.EVMRPCClient + + // ethSigner encapsulates EVM transaction signature handling + ethSigner ethtypes.Signer + + // zetaConnectorABI is the ABI of the ZetaConnector contract + zetaConnectorABI abi.ABI + + // erc20CustodyABI is the ABI of the ERC20Custody contract + erc20CustodyABI abi.ABI + + // zetaConnectorAddress is the address of the ZetaConnector contract + zetaConnectorAddress ethcommon.Address + + // er20CustodyAddress is the address of the ERC20Custody contract + er20CustodyAddress ethcommon.Address + + // outboundHashBeingReported is a map of outboundHash being reported outboundHashBeingReported map[string]bool } +// NewSigner creates a new EVM signer func NewSigner( chain chains.Chain, + zetacoreContext *clientcontext.ZetacoreContext, + tss interfaces.TSSSigner, + ts *metrics.TelemetryServer, + logger base.Logger, endpoint string, - tssSigner interfaces.TSSSigner, zetaConnectorABI string, erc20CustodyABI string, zetaConnectorAddress ethcommon.Address, erc20CustodyAddress ethcommon.Address, - coreContext *clientcontext.ZetacoreContext, - logger base.Logger, - ts *metrics.TelemetryServer, ) (*Signer, error) { + // create base signer + baseSigner := base.NewSigner(chain, zetacoreContext, tss, ts, logger) + + // create EVM client client, ethSigner, err := getEVMRPC(endpoint) if err != nil { return nil, err } + + // prepare ABIs connectorABI, err := abi.JSON(strings.NewReader(zetaConnectorABI)) if err != nil { return nil, err @@ -91,50 +104,42 @@ func NewSigner( } return &Signer{ - client: client, - chain: &chain, - tssSigner: tssSigner, - ethSigner: ethSigner, - zetaConnectorABI: connectorABI, - erc20CustodyABI: custodyABI, - zetaConnectorAddress: zetaConnectorAddress, - er20CustodyAddress: erc20CustodyAddress, - coreContext: coreContext, - logger: base.Logger{ - Std: logger.Std.With().Str("chain", chain.ChainName.String()).Str("module", "EVMSigner").Logger(), - Compliance: logger.Compliance, - }, - ts: ts, - mu: &sync.Mutex{}, + Signer: *baseSigner, + client: client, + ethSigner: ethSigner, + zetaConnectorABI: connectorABI, + erc20CustodyABI: custodyABI, + zetaConnectorAddress: zetaConnectorAddress, + er20CustodyAddress: erc20CustodyAddress, outboundHashBeingReported: make(map[string]bool), }, nil } // SetZetaConnectorAddress sets the zeta connector address func (signer *Signer) SetZetaConnectorAddress(addr ethcommon.Address) { - signer.mu.Lock() - defer signer.mu.Unlock() + signer.Mu().Lock() + defer signer.Mu().Unlock() signer.zetaConnectorAddress = addr } // SetERC20CustodyAddress sets the erc20 custody address func (signer *Signer) SetERC20CustodyAddress(addr ethcommon.Address) { - signer.mu.Lock() - defer signer.mu.Unlock() + signer.Mu().Lock() + defer signer.Mu().Unlock() signer.er20CustodyAddress = addr } // GetZetaConnectorAddress returns the zeta connector address func (signer *Signer) GetZetaConnectorAddress() ethcommon.Address { - signer.mu.Lock() - defer signer.mu.Unlock() + signer.Mu().Lock() + defer signer.Mu().Unlock() return signer.zetaConnectorAddress } // GetERC20CustodyAddress returns the erc20 custody address func (signer *Signer) GetERC20CustodyAddress() ethcommon.Address { - signer.mu.Lock() - defer signer.mu.Unlock() + signer.Mu().Lock() + defer signer.Mu().Unlock() return signer.er20CustodyAddress } @@ -149,15 +154,14 @@ func (signer *Signer) Sign( nonce uint64, height uint64, ) (*ethtypes.Transaction, []byte, []byte, error) { - log.Debug().Msgf("TSS SIGNER: %s", signer.tssSigner.Pubkey()) + log.Debug().Msgf("Sign: TSS signer: %s", signer.TSS().Pubkey()) // TODO: use EIP-1559 transaction type // https://github.com/zeta-chain/node/issues/1952 tx := ethtypes.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data) - hashBytes := signer.ethSigner.Hash(tx).Bytes() - sig, err := signer.tssSigner.Sign(hashBytes, height, nonce, signer.chain, "") + sig, err := signer.TSS().Sign(hashBytes, height, nonce, signer.Chain().ChainId, "") if err != nil { return nil, nil, nil, err } @@ -165,11 +169,11 @@ func (signer *Signer) Sign( log.Debug().Msgf("Sign: Signature: %s", hex.EncodeToString(sig[:])) pubk, err := crypto.SigToPub(hashBytes, sig[:]) if err != nil { - signer.logger.Std.Error().Err(err).Msgf("SigToPub error") + signer.Logger().Std.Error().Err(err).Msgf("SigToPub error") } addr := crypto.PubkeyToAddress(*pubk) - signer.logger.Std.Info().Msgf("Sign: Ecrecovery of signature: %s", addr.Hex()) + signer.Logger().Std.Info().Msgf("Sign: Ecrecovery of signature: %s", addr.Hex()) signedTX, err := tx.WithSignature(signer.ethSigner, sig[:]) if err != nil { return nil, nil, nil, err @@ -269,7 +273,7 @@ func (signer *Signer) SignRevertTx(txData *OutboundData) (*ethtypes.Transaction, func (signer *Signer) SignCancelTx(txData *OutboundData) (*ethtypes.Transaction, error) { tx, _, _, err := signer.Sign( nil, - signer.tssSigner.EVMAddress(), + signer.TSS().EVMAddress(), zeroValue, // zero out the amount to cancel the tx evm.EthTransferGasLimit, txData.gasPrice, @@ -326,7 +330,7 @@ func (signer *Signer) TryProcessOutbound( zetacoreClient interfaces.ZetacoreClient, height uint64, ) { - logger := signer.logger.Std.With(). + logger := signer.Logger().Std.With(). Str("outboundID", outboundID). Str("SendHash", cctx.Index). Logger() @@ -363,16 +367,16 @@ func (signer *Signer) TryProcessOutbound( toChain := chains.GetChainFromChainID(txData.toChainID.Int64()) // Get cross-chain flags - crossChainflags := signer.coreContext.GetCrossChainFlags() + crossChainflags := signer.ZetacoreContext().GetCrossChainFlags() // https://github.com/zeta-chain/node/issues/2050 var tx *ethtypes.Transaction // compliance check goes first if compliance.IsCctxRestricted(cctx) { compliance.PrintComplianceLog( logger, - signer.logger.Compliance, + signer.Logger().Compliance, true, - signer.chain.ChainId, + signer.Chain().ChainId, cctx.Index, cctx.InboundParams.Sender, txData.to.Hex(), @@ -529,22 +533,21 @@ func (signer *Signer) BroadcastOutbound( if tx == nil { logger.Warn().Msgf("BroadcastOutbound: no tx to broadcast %s", cctx.Index) } - // Try to broadcast transaction + + // broadcast transaction if tx != nil { outboundHash := tx.Hash().Hex() - logger.Info(). - Msgf("on chain %s nonce %d, outboundHash %s signer %s", signer.chain, cctx.GetCurrentOutboundParam().TssNonce, outboundHash, myID) - //if len(signers) == 0 || myid == signers[send.OutboundParams.Broadcaster] || myid == signers[int(send.OutboundParams.Broadcaster+1)%len(signers)] { + + // try broacasting tx with increasing backoff (1s, 2s, 4s, 8s, 16s) in case of RPC error backOff := 1000 * time.Millisecond - // retry loop: 1s, 2s, 4s, 8s, 16s in case of RPC error for i := 0; i < 5; i++ { - logger.Info(). - Msgf("broadcasting tx %s to chain %s: nonce %d, retry %d", outboundHash, toChain, cctx.GetCurrentOutboundParam().TssNonce, i) - // #nosec G404 randomness is not a security issue here - time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond) // FIXME: use backoff + time.Sleep(backOff) err := signer.Broadcast(tx) if err != nil { - log.Warn().Err(err).Msgf("Outbound Broadcast error") + log.Warn(). + Err(err). + Msgf("BroadcastOutbound: error broadcasting tx %s on chain %d nonce %d retry %d signer %s", + outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, i, myID) retry, report := zetacore.HandleBroadcastError( err, strconv.FormatUint(cctx.GetCurrentOutboundParam().TssNonce, 10), @@ -560,8 +563,8 @@ func (signer *Signer) BroadcastOutbound( backOff *= 2 continue } - logger.Info(). - Msgf("Broadcast success: nonce %d to chain %s outboundHash %s", cctx.GetCurrentOutboundParam().TssNonce, toChain, outboundHash) + logger.Info().Msgf("BroadcastOutbound: broadcasted tx %s on chain %d nonce %d signer %s", + outboundHash, toChain.ChainId, cctx.GetCurrentOutboundParam().TssNonce, myID) signer.reportToOutboundTracker(zetacoreClient, toChain.ChainId, tx.Nonce(), outboundHash, logger) break // successful broadcast; no need to retry } @@ -686,8 +689,8 @@ func (signer *Signer) reportToOutboundTracker( logger zerolog.Logger, ) { // skip if already being reported - signer.mu.Lock() - defer signer.mu.Unlock() + signer.Mu().Lock() + defer signer.Mu().Unlock() if _, found := signer.outboundHashBeingReported[outboundHash]; found { logger.Info(). Msgf("reportToOutboundTracker: outboundHash %s for chain %d nonce %d is being reported", outboundHash, chainID, nonce) @@ -698,9 +701,9 @@ func (signer *Signer) reportToOutboundTracker( // report to outbound tracker with goroutine go func() { defer func() { - signer.mu.Lock() + signer.Mu().Lock() delete(signer.outboundHashBeingReported, outboundHash) - signer.mu.Unlock() + signer.Mu().Unlock() }() // try monitoring tx inclusion status for 10 minutes diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index 186582dd24..410ea5adf3 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -43,20 +43,19 @@ func getNewEvmSigner(tss interfaces.TSSSigner) (*Signer, error) { mpiAddress := ConnectorAddress erc20CustodyAddress := ERC20CustodyAddress logger := base.Logger{} - ts := &metrics.TelemetryServer{} cfg := config.NewConfig() return NewSigner( chains.BscMainnet, - mocks.EVMRPCEnabled, + context.NewZetacoreContext(cfg), tss, + nil, + logger, + mocks.EVMRPCEnabled, config.GetConnectorABI(), config.GetERC20CustodyABI(), mpiAddress, - erc20CustodyAddress, - context.NewZetacoreContext(cfg), - logger, - ts) + erc20CustodyAddress) } // getNewEvmChainObserver creates a new EVM chain observer for testing @@ -256,7 +255,7 @@ func TestSigner_SignCancelTx(t *testing.T) { // Verify tx body basics // Note: Cancel tx sends 0 gas token to TSS self address - verifyTxBodyBasics(t, tx, evmSigner.tssSigner.EVMAddress(), txData.nonce, big.NewInt(0)) + verifyTxBodyBasics(t, tx, evmSigner.TSS().EVMAddress(), txData.nonce, big.NewInt(0)) }) t.Run("SignCancelTx - should fail if keysign fails", func(t *testing.T) { // Pause tss to make keysign fail diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go index 1d901d4f53..1ef94ec8de 100644 --- a/zetaclient/chains/interfaces/interfaces.go +++ b/zetaclient/chains/interfaces/interfaces.go @@ -167,7 +167,10 @@ type TSSSigner interface { // Note: it specifies optionalPubkey to use a different pubkey than the current pubkey set during keygen // TODO: check if optionalPubkey is needed // https://github.com/zeta-chain/node/issues/2085 - Sign(data []byte, height uint64, nonce uint64, chain *chains.Chain, optionalPubkey string) ([65]byte, error) + Sign(data []byte, height uint64, nonce uint64, chainID int64, optionalPubkey string) ([65]byte, error) + + // SignBatch signs the data in batch + SignBatch(digests [][]byte, height uint64, nonce uint64, chainID int64) ([][65]byte, error) EVMAddress() ethcommon.Address BTCAddress() string diff --git a/zetaclient/supplychecker/zeta_supply_checker.go b/zetaclient/supplychecker/zeta_supply_checker.go index f975c7eb88..3984b740ab 100644 --- a/zetaclient/supplychecker/zeta_supply_checker.go +++ b/zetaclient/supplychecker/zeta_supply_checker.go @@ -113,7 +113,6 @@ func (zs *ZetaSupplyChecker) Stop() { } func (zs *ZetaSupplyChecker) CheckZetaTokenSupply() error { - externalChainTotalSupply := sdkmath.ZeroInt() for _, chain := range zs.externalEvmChain { externalEvmChainParams, ok := zs.coreContext.GetEVMChainParams(chain.ChainId) diff --git a/zetaclient/testutils/mocks/btc_rpc.go b/zetaclient/testutils/mocks/btc_rpc.go index cfd63ef87b..01d286d31a 100644 --- a/zetaclient/testutils/mocks/btc_rpc.go +++ b/zetaclient/testutils/mocks/btc_rpc.go @@ -17,7 +17,9 @@ var _ interfaces.BTCRPCClient = &MockBTCRPCClient{} // MockBTCRPCClient is a mock implementation of the BTCRPCClient interface type MockBTCRPCClient struct { - Txs []*btcutil.Tx + err error + blockCount int64 + Txs []*btcutil.Tx } // NewMockBTCRPCClient creates a new mock BTC RPC client @@ -28,6 +30,10 @@ func NewMockBTCRPCClient() *MockBTCRPCClient { // Reset clears the mock data func (c *MockBTCRPCClient) Reset() *MockBTCRPCClient { + if c.err != nil { + return nil + } + c.Txs = []*btcutil.Tx{} return c } @@ -95,7 +101,10 @@ func (c *MockBTCRPCClient) GetRawTransactionVerbose(_ *chainhash.Hash) (*btcjson } func (c *MockBTCRPCClient) GetBlockCount() (int64, error) { - return 0, errors.New("not implemented") + if c.err != nil { + return 0, c.err + } + return c.blockCount, nil } func (c *MockBTCRPCClient) GetBlockHash(_ int64) (*chainhash.Hash, error) { @@ -118,6 +127,16 @@ func (c *MockBTCRPCClient) GetBlockHeader(_ *chainhash.Hash) (*wire.BlockHeader, // Feed data to the mock BTC RPC client for testing // ---------------------------------------------------------------------------- +func (c *MockBTCRPCClient) WithError(err error) *MockBTCRPCClient { + c.err = err + return c +} + +func (c *MockBTCRPCClient) WithBlockCount(blkCnt int64) *MockBTCRPCClient { + c.blockCount = blkCnt + return c +} + func (c *MockBTCRPCClient) WithRawTransaction(tx *btcutil.Tx) *MockBTCRPCClient { c.Txs = append(c.Txs, tx) return c diff --git a/zetaclient/testutils/mocks/evm_rpc.go b/zetaclient/testutils/mocks/evm_rpc.go index 926be6ec28..fa40357592 100644 --- a/zetaclient/testutils/mocks/evm_rpc.go +++ b/zetaclient/testutils/mocks/evm_rpc.go @@ -31,7 +31,9 @@ func (s subscription) Err() <-chan error { var _ interfaces.EVMRPCClient = &MockEvmClient{} type MockEvmClient struct { - Receipts []*ethtypes.Receipt + err error + blockNumber uint64 + Receipts []*ethtypes.Receipt } func NewMockEvmClient() *MockEvmClient { @@ -44,56 +46,92 @@ func (e *MockEvmClient) SubscribeFilterLogs( _ ethereum.FilterQuery, _ chan<- ethtypes.Log, ) (ethereum.Subscription, error) { + if e.err != nil { + return subscription{}, e.err + } return subscription{}, nil } func (e *MockEvmClient) CodeAt(_ context.Context, _ ethcommon.Address, _ *big.Int) ([]byte, error) { + if e.err != nil { + return nil, e.err + } return []byte{}, nil } func (e *MockEvmClient) CallContract(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) { + if e.err != nil { + return nil, e.err + } return []byte{}, nil } func (e *MockEvmClient) HeaderByNumber(_ context.Context, _ *big.Int) (*ethtypes.Header, error) { + if e.err != nil { + return nil, e.err + } return ðtypes.Header{}, nil } func (e *MockEvmClient) PendingCodeAt(_ context.Context, _ ethcommon.Address) ([]byte, error) { + if e.err != nil { + return nil, e.err + } return []byte{}, nil } func (e *MockEvmClient) PendingNonceAt(_ context.Context, _ ethcommon.Address) (uint64, error) { + if e.err != nil { + return 0, e.err + } return 0, nil } func (e *MockEvmClient) SuggestGasPrice(_ context.Context) (*big.Int, error) { + if e.err != nil { + return nil, e.err + } return big.NewInt(0), nil } func (e *MockEvmClient) SuggestGasTipCap(_ context.Context) (*big.Int, error) { + if e.err != nil { + return nil, e.err + } return big.NewInt(0), nil } func (e *MockEvmClient) EstimateGas(_ context.Context, _ ethereum.CallMsg) (gas uint64, err error) { + if e.err != nil { + return 0, e.err + } gas = 0 err = nil return } func (e *MockEvmClient) SendTransaction(_ context.Context, _ *ethtypes.Transaction) error { - return nil + return e.err } func (e *MockEvmClient) FilterLogs(_ context.Context, _ ethereum.FilterQuery) ([]ethtypes.Log, error) { + if e.err != nil { + return nil, e.err + } return []ethtypes.Log{}, nil } func (e *MockEvmClient) BlockNumber(_ context.Context) (uint64, error) { - return 0, nil + if e.err != nil { + return 0, e.err + } + return e.blockNumber, nil } func (e *MockEvmClient) BlockByNumber(_ context.Context, _ *big.Int) (*ethtypes.Block, error) { + if e.err != nil { + return nil, e.err + } return ðtypes.Block{}, nil } @@ -101,10 +139,17 @@ func (e *MockEvmClient) TransactionByHash( _ context.Context, _ ethcommon.Hash, ) (tx *ethtypes.Transaction, isPending bool, err error) { + if e.err != nil { + return nil, false, e.err + } return ðtypes.Transaction{}, false, nil } func (e *MockEvmClient) TransactionReceipt(_ context.Context, _ ethcommon.Hash) (*ethtypes.Receipt, error) { + if e.err != nil { + return nil, e.err + } + // pop a receipt from the list if len(e.Receipts) > 0 { receipt := e.Receipts[len(e.Receipts)-1] @@ -120,6 +165,9 @@ func (e *MockEvmClient) TransactionSender( _ ethcommon.Hash, _ uint, ) (ethcommon.Address, error) { + if e.err != nil { + return ethcommon.Address{}, e.err + } return ethcommon.Address{}, nil } @@ -131,6 +179,16 @@ func (e *MockEvmClient) Reset() *MockEvmClient { // ---------------------------------------------------------------------------- // Feed data to the mock evm client for testing // ---------------------------------------------------------------------------- +func (e *MockEvmClient) WithError(err error) *MockEvmClient { + e.err = err + return e +} + +func (e *MockEvmClient) WithBlockNumber(blockNumber uint64) *MockEvmClient { + e.blockNumber = blockNumber + return e +} + func (e *MockEvmClient) WithReceipt(receipt *ethtypes.Receipt) *MockEvmClient { e.Receipts = append(e.Receipts, receipt) return e diff --git a/zetaclient/testutils/mocks/tss_signer.go b/zetaclient/testutils/mocks/tss_signer.go index 87d2f2ac3b..ea439e23b6 100644 --- a/zetaclient/testutils/mocks/tss_signer.go +++ b/zetaclient/testutils/mocks/tss_signer.go @@ -67,7 +67,7 @@ func (s *TSS) WithPrivKey(privKey *ecdsa.PrivateKey) *TSS { } // Sign uses test key unrelated to any tss key in production -func (s *TSS) Sign(data []byte, _ uint64, _ uint64, _ *chains.Chain, _ string) ([65]byte, error) { +func (s *TSS) Sign(data []byte, _ uint64, _ uint64, _ int64, _ string) ([65]byte, error) { // return error if tss is paused if s.paused { return [65]byte{}, fmt.Errorf("tss is paused") @@ -83,6 +83,17 @@ func (s *TSS) Sign(data []byte, _ uint64, _ uint64, _ *chains.Chain, _ string) ( return sigbyte, nil } +// SignBatch uses test key unrelated to any tss key in production +func (s *TSS) SignBatch(_ [][]byte, _ uint64, _ uint64, _ int64) ([][65]byte, error) { + // return error if tss is paused + if s.paused { + return nil, fmt.Errorf("tss is paused") + } + + // mock not implemented yet + return nil, fmt.Errorf("not implemented") +} + func (s *TSS) Pubkey() []byte { publicKeyBytes := crypto.FromECDSAPub(&s.PrivKey.PublicKey) return publicKeyBytes diff --git a/zetaclient/tss/tss_signer.go b/zetaclient/tss/tss_signer.go index 2915dd6d0a..8fdd0384ee 100644 --- a/zetaclient/tss/tss_signer.go +++ b/zetaclient/tss/tss_signer.go @@ -218,7 +218,7 @@ func (tss *TSS) Sign( digest []byte, height uint64, nonce uint64, - chain *chains.Chain, + chainID int64, optionalPubKey string, ) ([65]byte, error) { H := digest @@ -250,8 +250,8 @@ func (tss *TSS) Sign( // post blame data if enabled if IsEnvFlagEnabled(envFlagPostBlame) { digest := hex.EncodeToString(digest) - index := observertypes.GetBlameIndex(chain.ChainId, nonce, digest, height) - zetaHash, err := tss.ZetacoreClient.PostBlameData(&ksRes.Blame, chain.ChainId, index) + index := observertypes.GetBlameIndex(chainID, nonce, digest, height) + zetaHash, err := tss.ZetacoreClient.PostBlameData(&ksRes.Blame, chainID, index) if err != nil { log.Error().Err(err).Msg("error sending blame data to core") return [65]byte{}, err @@ -304,7 +304,7 @@ func (tss *TSS) Sign( // SignBatch is hash of some data // digest should be batch of hashes of some data -func (tss *TSS) SignBatch(digests [][]byte, height uint64, nonce uint64, chain *chains.Chain) ([][65]byte, error) { +func (tss *TSS) SignBatch(digests [][]byte, height uint64, nonce uint64, chainID int64) ([][65]byte, error) { tssPubkey := tss.CurrentPubkey digestBase64 := make([]string, len(digests)) for i, digest := range digests { @@ -326,8 +326,8 @@ func (tss *TSS) SignBatch(digests [][]byte, height uint64, nonce uint64, chain * // post blame data if enabled if IsEnvFlagEnabled(envFlagPostBlame) { digest := combineDigests(digestBase64) - index := observertypes.GetBlameIndex(chain.ChainId, nonce, hex.EncodeToString(digest), height) - zetaHash, err := tss.ZetacoreClient.PostBlameData(&ksRes.Blame, chain.ChainId, index) + index := observertypes.GetBlameIndex(chainID, nonce, hex.EncodeToString(digest), height) + zetaHash, err := tss.ZetacoreClient.PostBlameData(&ksRes.Blame, chainID, index) if err != nil { log.Error().Err(err).Msg("error sending blame data to core") return [][65]byte{}, err diff --git a/zetaclient/zetacore/client.go b/zetaclient/zetacore/client.go index d64fd56db1..3b85296fe1 100644 --- a/zetaclient/zetacore/client.go +++ b/zetaclient/zetacore/client.go @@ -57,7 +57,6 @@ func NewClient( hsmMode bool, telemetry *metrics.TelemetryServer, ) (*Client, error) { - // main module logger logger := log.With().Str("module", "ZetacoreClient").Logger() cfg := config.ClientConfiguration{