From bb0a33f54b8648405b774b2c2526ebccaf050bd7 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 11 Mar 2024 23:24:41 +0100 Subject: [PATCH] Mumbai soak fix light (#12384) * use EIP-1559 for sending funds (if enabled), validate Seth config, return early on error during funds sending * hacky fix for Duration copying for now --- integration-tests/actions/seth/actions.go | 45 +++++++++++------- integration-tests/chaos/ocr_chaos_test.go | 2 + .../docker/test_env/test_env_builder.go | 4 ++ integration-tests/testconfig/default.toml | 7 +-- integration-tests/testconfig/testconfig.go | 11 +++++ integration-tests/testsetups/ocr.go | 2 + integration-tests/utils/seth.go | 47 +++++++++++++++++++ 7 files changed, 97 insertions(+), 21 deletions(-) diff --git a/integration-tests/actions/seth/actions.go b/integration-tests/actions/seth/actions.go index 990b195a800..8de166f0fce 100644 --- a/integration-tests/actions/seth/actions.go +++ b/integration-tests/actions/seth/actions.go @@ -52,7 +52,6 @@ func FundChainlinkNodes( privateKey *ecdsa.PrivateKey, amount *big.Float, ) error { - fundingErrors := []error{} for _, cl := range nodes { toAddress, err := cl.PrimaryEthAddress() if err != nil { @@ -70,12 +69,12 @@ func FundChainlinkNodes( PrivateKey: privateKey, }) if err != nil { - fundingErrors = append(fundingErrors, err) - logger.Err(err). Str("From", fromAddress.Hex()). Str("To", toAddress). Msg("Failed to fund Chainlink node") + + return err } txHash := "(none)" @@ -91,14 +90,6 @@ func FundChainlinkNodes( Msg("Funded Chainlink node") } - if len(fundingErrors) > 0 { - var wrapped error - for _, e := range fundingErrors { - wrapped = errors.Wrapf(e, ",") - } - return fmt.Errorf("failed to fund chainlink nodes due to following errors: %w", wrapped) - } - return nil } @@ -130,14 +121,29 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa gasLimit = *payload.GasLimit } - rawTx := &types.LegacyTx{ - Nonce: nonce, - To: &payload.ToAddress, - Value: payload.Amount, - Gas: gasLimit, - GasPrice: big.NewInt(client.Cfg.Network.GasPrice), + var signedTx *types.Transaction + + if client.Cfg.Network.EIP1559DynamicFees { + rawTx := &types.DynamicFeeTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: gasLimit, + GasFeeCap: big.NewInt(client.Cfg.Network.GasFeeCap), + GasTipCap: big.NewInt(client.Cfg.Network.GasTipCap), + } + signedTx, err = types.SignNewTx(payload.PrivateKey, types.NewLondonSigner(big.NewInt(client.ChainID)), rawTx) + } else { + rawTx := &types.LegacyTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: gasLimit, + GasPrice: big.NewInt(client.Cfg.Network.GasPrice), + } + signedTx, err = types.SignNewTx(payload.PrivateKey, types.NewEIP155Signer(big.NewInt(client.ChainID)), rawTx) } - signedTx, err := types.SignNewTx(payload.PrivateKey, types.NewEIP155Signer(big.NewInt(client.ChainID)), rawTx) + if err != nil { return nil, errors.Wrap(err, "failed to sign tx") } @@ -157,6 +163,9 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Uint64("Nonce", nonce). Uint64("Gas Limit", gasLimit). Int64("Gas Price", client.Cfg.Network.GasPrice). + Int64("Gas Fee Cap", client.Cfg.Network.GasFeeCap). + Int64("Gas Tip Cap", client.Cfg.Network.GasTipCap). + Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). Msg("Sent funds") return client.WaitMined(ctx, logger, client.Client, signedTx) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index b2adec04117..c99318d51dd 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -171,6 +171,8 @@ func TestOCRChaos(t *testing.T) { network = utils.MustReplaceSimulatedNetworkUrlWithK8(l, network, *testEnvironment) sethCfg := utils.MergeSethAndEvmNetworkConfigs(l, network, *readSethCfg) + err = utils.ValidateSethNetworkConfig(sethCfg.Network) + require.NoError(t, err, "Error validating seth network config") seth, err := seth.NewClientWithConfig(&sethCfg) require.NoError(t, err, "Error creating seth client") diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 127ec921ef7..7c50bd1c725 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -391,6 +391,10 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if b.hasSeth { readSethCfg := b.testConfig.GetSethConfig() sethCfg := utils.MergeSethAndEvmNetworkConfigs(b.l, networkConfig, *readSethCfg) + err = utils.ValidateSethNetworkConfig(sethCfg.Network) + if err != nil { + return nil, err + } seth, err := seth.NewClientWithConfig(&sethCfg) if err != nil { return nil, err diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 6ba70d31216..06c792be882 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -86,12 +86,13 @@ gas_tip_cap = 10_000_000_000 name = "Mumbai" chain_id = "80001" transaction_timeout = "3m" -transfer_gas_fee = 21_000 +transfer_gas_fee = 40_000 +gas_limit = 6_000_000 # legacy transactions #gas_price = 1_800_000_000 # EIP-1559 transactions eip_1559_dynamic_fees = true -gas_fee_cap = 1_800_000_000 +gas_fee_cap = 3_800_000_000 gas_tip_cap = 1_800_000_000 [[Seth.networks]] @@ -104,5 +105,5 @@ gas_limit = 3_000_000 gas_price = 50_000_000 # EIP-1559 transactions #eip_1559_dynamic_fees = true -gas_fee_cap = 1_800_000_000 +gas_fee_cap = 3_800_000_000 gas_tip_cap = 1_800_000_000 \ No newline at end of file diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index cd44eb5aa33..c83b67f204b 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -581,6 +581,17 @@ func handleDefaultConfigOverride(logger zerolog.Logger, filename, configurationN return errors.Wrapf(err, "error reading file %s", filename) } + // temporary fix for Duration not being correctly copied + if oldConfig != nil && oldConfig.Seth != nil && oldConfig.Seth.Networks != nil { + for i, old_network := range oldConfig.Seth.Networks { + for _, target_network := range target.Seth.Networks { + if old_network.ChainID == target_network.ChainID { + oldConfig.Seth.Networks[i].TxnTimeout = old_network.TxnTimeout + } + } + } + } + // override instead of merging if (newConfig.Seth != nil && len(newConfig.Seth.Networks) > 0) && (oldConfig != nil && oldConfig.Seth != nil && len(oldConfig.Seth.Networks) > 0) { for i, old_network := range oldConfig.Seth.Networks { diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index f3a7a77e8cf..14e337a43b2 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -171,6 +171,8 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { require.NotNil(o.t, readSethCfg, "Seth config shouldn't be nil") sethCfg := utils.MergeSethAndEvmNetworkConfigs(o.log, network, *readSethCfg) + err = utils.ValidateSethNetworkConfig(sethCfg.Network) + require.NoError(o.t, err, "Error validating seth network config") seth, err := seth.NewClientWithConfig(&sethCfg) require.NoError(o.t, err, "Error creating seth client") diff --git a/integration-tests/utils/seth.go b/integration-tests/utils/seth.go index adb63e4f9c2..c2d4f743a6b 100644 --- a/integration-tests/utils/seth.go +++ b/integration-tests/utils/seth.go @@ -2,6 +2,7 @@ package utils import ( "fmt" + "strconv" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" @@ -82,3 +83,49 @@ func MustReplaceSimulatedNetworkUrlWithK8(l zerolog.Logger, network blockchain.E return network } + +// ValidateSethNetworkConfig validates the Seth network config +func ValidateSethNetworkConfig(cfg *seth.Network) error { + if cfg == nil { + return fmt.Errorf("Network cannot be nil") + } + if cfg.ChainID == "" { + return fmt.Errorf("ChainID is required") + } + _, err := strconv.Atoi(cfg.ChainID) + if err != nil { + return fmt.Errorf("ChainID needs to be a number") + } + if cfg.URLs == nil || len(cfg.URLs) == 0 { + return fmt.Errorf("URLs are required") + } + if cfg.PrivateKeys == nil || len(cfg.PrivateKeys) == 0 { + return fmt.Errorf("PrivateKeys are required") + } + if cfg.TransferGasFee == 0 { + return fmt.Errorf("TransferGasFee needs to be above 0. It's the gas fee for a simple transfer transaction") + } + if cfg.TxnTimeout.Duration() == 0 { + return fmt.Errorf("TxnTimeout needs to be above 0. It's the timeout for a transaction") + } + if cfg.GasLimit == 0 { + return fmt.Errorf("GasLimit needs to be above 0. It's the gas limit for a transaction") + } + if cfg.EIP1559DynamicFees { + if cfg.GasFeeCap == 0 { + return fmt.Errorf("GasFeeCap needs to be above 0. It's the maximum fee per gas for a transaction (including tip)") + } + if cfg.GasTipCap == 0 { + return fmt.Errorf("GasTipCap needs to be above 0. It's the maximum tip per gas for a transaction") + } + if cfg.GasFeeCap <= cfg.GasTipCap { + return fmt.Errorf("GasFeeCap needs to be above GasTipCap (as it is base fee + tip cap)") + } + } else { + if cfg.GasPrice == 0 { + return fmt.Errorf("GasPrice needs to be above 0. It's the price of gas for a transaction") + } + } + + return nil +}