From d2f3593083e1fa1af120086c0ee77c16346d8c06 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 11:36:53 -0500 Subject: [PATCH 01/23] Feat: initial refactor of setGasPrice() --- ethergo/submitter/submitter.go | 162 +++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index a9f35ba0b4..cd923034b6 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -354,91 +354,157 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, ctx, span := t.metrics.Tracer().Start(ctx, "submitter.setGasPrice") chainID := int(bigChainID.Uint64()) - maxPrice := t.config.GetMaxGasPrice(chainID) + useDynamic := t.config.SupportsEIP1559(chainID) + shouldBump := prevTx != nil defer func() { - if transactor.GasPrice != nil && maxPrice.Cmp(transactor.GasPrice) < 0 { - transactor.GasPrice = maxPrice + span.SetAttributes( + attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), + attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), + attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), + ) + metrics.EndSpanWithErr(span, err) + }() + + t.populateGasFromPrevTx(ctx, transactor, prevTx, useDynamic) + t.applyGasFloor(ctx, transactor, chainID, shouldBump) + + err = t.applyGasFromOracle(ctx, transactor, client, useDynamic) + if err != nil { + return fmt.Errorf("could not populate gas from oracle: %w", err) + } + + err = t.applyGasCeil(ctx, transactor, chainID, useDynamic) + if err != nil { + return fmt.Errorf("could not apply gas ceil: %w", err) + } + return nil +} + +func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor *bind.TransactOpts, prevTx *types.Transaction, currentDynamic bool) { + if prevTx == nil { + return + } + prevDynamic := prevTx.Type() == types.DynamicFeeTxType + if currentDynamic { + if prevDynamic { + transactor.GasFeeCap = core.CopyBigInt(prevTx.GasFeeCap()) + transactor.GasTipCap = core.CopyBigInt(prevTx.GasTipCap()) + } else { + transactor.GasFeeCap = core.CopyBigInt(prevTx.GasPrice()) + transactor.GasTipCap = core.CopyBigInt(prevTx.GasPrice()) } - if transactor.GasFeeCap != nil && maxPrice.Cmp(transactor.GasFeeCap) < 0 { - transactor.GasFeeCap = maxPrice + } else { + if prevDynamic { + transactor.GasPrice = core.CopyBigInt(prevTx.GasFeeCap()) + } else { + transactor.GasPrice = core.CopyBigInt(prevTx.GasPrice()) } + } +} +func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, shouldBump bool) { + ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") + + defer func() { span.SetAttributes( attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), + attribute.Bool("should_bump", shouldBump), ) - metrics.EndSpanWithErr(span, err) + metrics.EndSpan(span) }() - // TODO: cache both of these values - shouldBump := true - useEIP1559 := t.config.SupportsEIP1559(chainID) - if useEIP1559 { - transactor.GasFeeCap, err = client.SuggestGasPrice(ctx) - if err != nil { - return fmt.Errorf("could not get gas price: %w", err) + gasFloor := t.config.GetBaseGasPrice(chainID) + useDynamic := t.config.SupportsEIP1559(chainID) + if shouldBump { + bumpPct := t.config.GetGasBumpPercentage(chainID) + if useDynamic { + if transactor.GasFeeCap == nil { + transactor.GasFeeCap = gasFloor + span.AddEvent("gas fee cap is nil; setting to gas floor") + } else { + transactor.GasFeeCap = gas.BumpByPercent(transactor.GasFeeCap, bumpPct) + } + if transactor.GasTipCap == nil { + transactor.GasTipCap = gasFloor + span.AddEvent("gas tip cap is nil; setting to gas floor") + } else { + transactor.GasTipCap = gas.BumpByPercent(transactor.GasTipCap, bumpPct) + } + } else { + transactor.GasPrice = gas.BumpByPercent(transactor.GasPrice, bumpPct) } - // don't bump fee cap if we hit the max configured gas price - if transactor.GasFeeCap.Cmp(maxPrice) > 0 { - transactor.GasFeeCap = maxPrice - shouldBump = false - span.AddEvent("not bumping fee cap since max price is reached") + } else { + if useDynamic { + if transactor.GasFeeCap == nil || transactor.GasFeeCap.Cmp(gasFloor) < 0 { + transactor.GasFeeCap = gasFloor + } + if transactor.GasTipCap == nil || transactor.GasTipCap.Cmp(gasFloor) < 0 { + transactor.GasTipCap = gasFloor + } + } else { + if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { + transactor.GasPrice = gasFloor + } } + } + return +} - transactor.GasTipCap, err = client.SuggestGasTipCap(ctx) +func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bind.TransactOpts, client client.EVM, useDynamic bool) (err error) { + if useDynamic { + suggestedGasFeeCap, err := client.SuggestGasPrice(ctx) + if err != nil { + return fmt.Errorf("could not get gas fee cap: %w", err) + } + transactor.GasFeeCap = maxOfBig(transactor.GasFeeCap, suggestedGasFeeCap) + suggestedGasTipCap, err := client.SuggestGasTipCap(ctx) if err != nil { return fmt.Errorf("could not get gas tip cap: %w", err) } + transactor.GasTipCap = maxOfBig(transactor.GasTipCap, suggestedGasTipCap) } else { - transactor.GasPrice, err = client.SuggestGasPrice(ctx) + suggestedGasPrice, err := client.SuggestGasPrice(ctx) if err != nil { return fmt.Errorf("could not get gas price: %w", err) } + transactor.GasPrice = maxOfBig(transactor.GasPrice, suggestedGasPrice) } - t.applyBaseGasPrice(transactor, chainID) + return nil +} - //nolint: nestif - if prevTx != nil && shouldBump { - gasBlock, err := t.getGasBlock(ctx, client, chainID) - if err != nil { - span.AddEvent("could not get gas block", trace.WithAttributes(attribute.String("error", err.Error()))) - return err - } +func (t *txSubmitterImpl) applyGasCeil(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic bool) (err error) { + ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") - // if the prev tx was greater than this one, we should bump the gas price from that point - if prevTx.Type() == types.LegacyTxType { - if prevTx.GasPrice().Cmp(transactor.GasPrice) > 0 { - transactor.GasPrice = core.CopyBigInt(prevTx.GasPrice()) - } - } else { - if prevTx.GasTipCap().Cmp(transactor.GasTipCap) > 0 { - transactor.GasTipCap = core.CopyBigInt(prevTx.GasTipCap()) - } + maxPrice := t.config.GetMaxGasPrice(chainID) - if prevTx.GasFeeCap().Cmp(transactor.GasFeeCap) > 0 { - transactor.GasFeeCap = core.CopyBigInt(prevTx.GasFeeCap()) - } + defer func() { + span.SetAttributes(attribute.String("max_price", bigPtrToString(maxPrice))) + metrics.EndSpanWithErr(span, err) + }() + + if useDynamic { + if transactor.GasFeeCap.Cmp(maxPrice) > 0 { + return fmt.Errorf("gas fee cap %s exceeds max price %s", transactor.GasFeeCap, maxPrice) } - gas.BumpGasFees(transactor, t.config.GetGasBumpPercentage(chainID), gasBlock.BaseFee, maxPrice) + // TODO: should maxPrice apply to GasTipCap as well? } else { - // if we're not bumping, we should still make sure the gas price is at least 10 because 10% of 10 wei is a whole number. - // TODO: this should be customizable. - if useEIP1559 { - transactor.GasTipCap = maxOfBig(transactor.GasTipCap, big.NewInt(10)) - } else { - transactor.GasPrice = maxOfBig(transactor.GasPrice, big.NewInt(10)) + if transactor.GasPrice.Cmp(maxPrice) > 0 { + return fmt.Errorf("gas price %s exceeds max price %s", transactor.GasPrice, maxPrice) } } return nil } -// b must not be nil. func maxOfBig(a, b *big.Int) *big.Int { if a == nil { return b } + if b == nil { + return a + } if a.Cmp(b) > 0 { return a } From f60ee8f5e7a2c002c7eab3513bf29cf3a73ef2aa Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 11:41:53 -0500 Subject: [PATCH 02/23] Feat: add more tracing --- ethergo/submitter/submitter.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index cd923034b6..bc6c1b2a05 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -359,6 +359,9 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, defer func() { span.SetAttributes( + attribute.Int(metrics.ChainID, chainID), + attribute.Bool("use_dynamic", useDynamic), + attribute.Bool("should_bump", shouldBump), attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), @@ -385,6 +388,18 @@ func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor if prevTx == nil { return } + + ctx, span := t.metrics.Tracer().Start(ctx, "submitter.populateGasFromPrevTx") + + defer func() { + span.SetAttributes( + attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), + attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), + attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), + ) + metrics.EndSpan(span) + }() + prevDynamic := prevTx.Type() == types.DynamicFeeTxType if currentDynamic { if prevDynamic { @@ -454,6 +469,12 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr } func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bind.TransactOpts, client client.EVM, useDynamic bool) (err error) { + ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") + + defer func() { + metrics.EndSpanWithErr(span, err) + }() + if useDynamic { suggestedGasFeeCap, err := client.SuggestGasPrice(ctx) if err != nil { @@ -465,12 +486,22 @@ func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bi return fmt.Errorf("could not get gas tip cap: %w", err) } transactor.GasTipCap = maxOfBig(transactor.GasTipCap, suggestedGasTipCap) + span.SetAttributes( + attribute.String("suggested_gas_fee_cap", bigPtrToString(suggestedGasFeeCap)), + attribute.String("suggested_gas_tip_cap", bigPtrToString(suggestedGasTipCap)), + attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), + attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), + ) } else { suggestedGasPrice, err := client.SuggestGasPrice(ctx) if err != nil { return fmt.Errorf("could not get gas price: %w", err) } transactor.GasPrice = maxOfBig(transactor.GasPrice, suggestedGasPrice) + span.SetAttributes( + attribute.String("suggested_gas_price", bigPtrToString(suggestedGasPrice)), + attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), + ) } return nil } From ecf6ede41d10ff3a7b5cea6201061a834f28b110 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 11:47:08 -0500 Subject: [PATCH 03/23] Cleanup: comments --- ethergo/submitter/submitter.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index bc6c1b2a05..43a11204fb 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -346,9 +346,9 @@ func (t *txSubmitterImpl) txTypeForChain(chainID *big.Int) (txType uint8) { } // setGasPrice sets the gas price for the transaction. -// it bumps if prevtx is set -// nolint: cyclop -// TODO: use options. +// If a prevTx is specified, a bump will be attempted; otherwise values will be +// set from the gas oracle. +// If gas values exceed the configured max, an error will be returned. func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, transactor *bind.TransactOpts, bigChainID *big.Int, prevTx *types.Transaction) (err error) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.setGasPrice") @@ -384,6 +384,9 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, return nil } +// populateGasFromPrevTx populates the gas fields from the previous transaction. +// Note that in the event of a tx type mismatch, gasFeeCap is copied to gasPrice, +// and gasPrice is copied to both gasFeeCap and gasTipCap in the opposite scenario. func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor *bind.TransactOpts, prevTx *types.Transaction, currentDynamic bool) { if prevTx == nil { return @@ -418,6 +421,8 @@ func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor } } +// applyGasFloor applies the min gas price from the config if values are unset. +// Otherwise, gas values are bumped by the configured GasBumpPercentage. func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, shouldBump bool) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") @@ -468,6 +473,8 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr return } +// applyGasFromOracle fetches gas values from a RPC endpoint and attempts to set them. +// If values are already specified, they will be overridden if the oracle values are higher. func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bind.TransactOpts, client client.EVM, useDynamic bool) (err error) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") @@ -506,6 +513,8 @@ func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bi return nil } +// applyGasCeil evaluates current gas values versus the configured maximum, and +// returns an error if they exceed the maximum. func (t *txSubmitterImpl) applyGasCeil(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic bool) (err error) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") From 7012588d51834c30b8dc0b725514c88ca6d97991 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 11:49:31 -0500 Subject: [PATCH 04/23] Feat: BaseGasPrice -> MinGasPrice --- ethergo/submitter/config/config.go | 28 +++++++++---------- ethergo/submitter/config/iconfig_generated.go | 8 +++--- ethergo/submitter/submitter.go | 10 +++---- ethergo/submitter/submitter_test.go | 8 +++--- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/ethergo/submitter/config/config.go b/ethergo/submitter/config/config.go index 1f1fd4c12e..c0e90cdfdd 100644 --- a/ethergo/submitter/config/config.go +++ b/ethergo/submitter/config/config.go @@ -31,8 +31,8 @@ type ChainConfig struct { DoNotBatch bool `yaml:"skip_batching"` // MaxGasPrice is the maximum gas price to use for transactions MaxGasPrice *big.Int `yaml:"max_gas_price"` - // BaseGasPrice is the gas price that will be used if 0 is returned from the gas price oracle - BaseGasPrice *big.Int `yaml:"base_gas_price"` + // MinGasPrice is the gas price that will be used if 0 is returned from the gas price oracle + MinGasPrice *big.Int `yaml:"min_gas_price"` // BumpIntervalSeconds is the number of seconds to wait before bumping a transaction BumpIntervalSeconds int `yaml:"bump_interval_seconds"` // GasBumpPercentages is the percentage to bump the gas price by @@ -67,8 +67,8 @@ const ( // DefaultMaxPrice is the default max price of a tx. var DefaultMaxPrice = big.NewInt(500 * params.GWei) -// DefaultBaseGasPrice is the default max price of a tx. -var DefaultBaseGasPrice = big.NewInt(1 * params.GWei) +// DefaultMinGasPrice is the default min price of a tx. +var DefaultMinGasPrice = big.NewInt(10 * params.GWei) // note: there's probably a way to clean these getters up with generics, the real problem comes with the fact that // that this would require the caller to override the entire struct, which is not ideal.. @@ -110,17 +110,17 @@ func (c *Config) GetMaxGasPrice(chainID int) (maxPrice *big.Int) { return } -// GetBaseGasPrice returns the maximum gas price to use for transactions. -func (c *Config) GetBaseGasPrice(chainID int) (basePrice *big.Int) { - basePrice = c.BaseGasPrice +// GetMinGasPrice returns the maximum gas price to use for transactions. +func (c *Config) GetMinGasPrice(chainID int) (minPrice *big.Int) { + minPrice = c.MinGasPrice chainConfig, ok := c.Chains[chainID] - if ok && chainConfig.BaseGasPrice != nil { - basePrice = chainConfig.BaseGasPrice + if ok && chainConfig.MinGasPrice != nil { + minPrice = chainConfig.MinGasPrice } - if basePrice == nil || basePrice == big.NewInt(0) { - basePrice = DefaultBaseGasPrice + if minPrice == nil || minPrice == big.NewInt(0) { + minPrice = DefaultMinGasPrice } return } @@ -217,9 +217,9 @@ func (c *Config) SetGlobalMaxGasPrice(maxPrice *big.Int) { c.MaxGasPrice = maxPrice } -// SetBaseGasPrice is a helper function that sets the base gas price. -func (c *Config) SetBaseGasPrice(basePrice *big.Int) { - c.BaseGasPrice = basePrice +// SetMinGasPrice is a helper function that sets the base gas price. +func (c *Config) SetMinGasPrice(basePrice *big.Int) { + c.MinGasPrice = basePrice } // SetGlobalEIP1559Support is a helper function that sets the global EIP1559 support. diff --git a/ethergo/submitter/config/iconfig_generated.go b/ethergo/submitter/config/iconfig_generated.go index b6aac67620..86292a74e1 100644 --- a/ethergo/submitter/config/iconfig_generated.go +++ b/ethergo/submitter/config/iconfig_generated.go @@ -15,8 +15,8 @@ type IConfig interface { GetBatch(chainID int) bool // GetMaxGasPrice returns the maximum gas price to use for transactions. GetMaxGasPrice(chainID int) (maxPrice *big.Int) - // GetBaseGasPrice returns the maximum gas price to use for transactions. - GetBaseGasPrice(chainID int) (basePrice *big.Int) + // GetMinGasPrice returns the maximum gas price to use for transactions. + GetMinGasPrice(chainID int) (basePrice *big.Int) // GetBumpInterval returns the number of seconds to wait before bumping a transaction // TODO: test this method. GetBumpInterval(chainID int) time.Duration @@ -35,8 +35,8 @@ type IConfig interface { SupportsEIP1559(chainID int) bool // SetGlobalMaxGasPrice is a helper function that sets the global gas price. SetGlobalMaxGasPrice(maxPrice *big.Int) - // SetBaseGasPrice is a helper function that sets the base gas price. - SetBaseGasPrice(basePrice *big.Int) + // SetMinGasPrice is a helper function that sets the base gas price. + SetMinGasPrice(basePrice *big.Int) // SetGlobalEIP1559Support is a helper function that sets the global EIP1559 support. SetGlobalEIP1559Support(supportsEIP1559 bool) } diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 43a11204fb..e5a07048c2 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -436,7 +436,7 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr metrics.EndSpan(span) }() - gasFloor := t.config.GetBaseGasPrice(chainID) + gasFloor := t.config.GetMinGasPrice(chainID) useDynamic := t.config.SupportsEIP1559(chainID) if shouldBump { bumpPct := t.config.GetGasBumpPercentage(chainID) @@ -551,16 +551,16 @@ func maxOfBig(a, b *big.Int) *big.Int { return b } -// applyBaseGasPrice applies the base gas price to the transactor if a gas price value is zero. -func (t *txSubmitterImpl) applyBaseGasPrice(transactor *bind.TransactOpts, chainID int) { +// applyMinGasPrice applies the base gas price to the transactor if a gas price value is zero. +func (t *txSubmitterImpl) applyMinGasPrice(transactor *bind.TransactOpts, chainID int) { if t.config.SupportsEIP1559(chainID) { if transactor.GasFeeCap == nil || transactor.GasFeeCap.Cmp(big.NewInt(0)) == 0 { - transactor.GasFeeCap = t.config.GetBaseGasPrice(chainID) + transactor.GasFeeCap = t.config.GetMinGasPrice(chainID) } // TODO: we need to keep gas tip cap non-zero, but below the base gas price. } else { if transactor.GasPrice == nil || transactor.GasPrice.Cmp(big.NewInt(0)) == 0 { - transactor.GasPrice = t.config.GetBaseGasPrice(chainID) + transactor.GasPrice = t.config.GetMinGasPrice(chainID) } } } diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index b716165038..38953c5c5a 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -71,15 +71,15 @@ func (s *SubmitterSuite) TestSetGasPrice() { // 4. Test with zero gas price, should return base gas price cfg.SetGlobalEIP1559Support(false) - baseGasPrice := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) - cfg.SetBaseGasPrice(baseGasPrice) + minGasPrice := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) + cfg.SetMinGasPrice(minGasPrice) gasPrice = big.NewInt(0) client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Return(gasPrice, nil) err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) s.Require().NoError(err) - s.Equal(baseGasPrice, transactor.GasPrice, testsuite.BigIntComparer()) + s.Equal(minGasPrice, transactor.GasPrice, testsuite.BigIntComparer()) // 5. Test with zero gas price with EIP1559, should return base gas price cfg.SetGlobalEIP1559Support(true) @@ -89,7 +89,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) s.Require().NoError(err) - s.Equal(baseGasPrice, transactor.GasTipCap, testsuite.BigIntComparer()) + s.Equal(minGasPrice, transactor.GasTipCap, testsuite.BigIntComparer()) // 6. Test with bump (TODO) // 7. Test with bump and max (TODO) From a0426d36c04ca3ba7b0955dcb3db5919a5f660d6 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 11:49:56 -0500 Subject: [PATCH 05/23] Cleanup: remove applyMinGasPrice() --- ethergo/submitter/submitter.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index e5a07048c2..78462ab2b6 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -551,20 +551,6 @@ func maxOfBig(a, b *big.Int) *big.Int { return b } -// applyMinGasPrice applies the base gas price to the transactor if a gas price value is zero. -func (t *txSubmitterImpl) applyMinGasPrice(transactor *bind.TransactOpts, chainID int) { - if t.config.SupportsEIP1559(chainID) { - if transactor.GasFeeCap == nil || transactor.GasFeeCap.Cmp(big.NewInt(0)) == 0 { - transactor.GasFeeCap = t.config.GetMinGasPrice(chainID) - } - // TODO: we need to keep gas tip cap non-zero, but below the base gas price. - } else { - if transactor.GasPrice == nil || transactor.GasPrice.Cmp(big.NewInt(0)) == 0 { - transactor.GasPrice = t.config.GetMinGasPrice(chainID) - } - } -} - // getGasBlock gets the gas block for the given chain. func (t *txSubmitterImpl) getGasBlock(ctx context.Context, chainClient client.EVM, chainID int) (gasBlock *types.Header, err error) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.getGasBlock") From 850ab7668cc53574ff66aba7d5dad4d9ad896a3e Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 12:48:09 -0500 Subject: [PATCH 06/23] Feat: initial test cases --- ethergo/submitter/submitter_test.go | 206 +++++++++++++++++++++++----- 1 file changed, 173 insertions(+), 33 deletions(-) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index 38953c5c5a..fcdd3032cb 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -7,6 +7,7 @@ import ( "github.com/brianvoe/gofakeit/v6" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/mock" "github.com/synapsecns/sanguine/core/testsuite" clientMocks "github.com/synapsecns/sanguine/ethergo/client/mocks" @@ -30,6 +31,140 @@ func (s *SubmitterSuite) TestSetGasPrice() { signer := localsigner.NewSigner(wall.PrivateKey()) + legacyChainID := s.testBackends[0].GetBigChainID() + dynamicChainID := s.testBackends[1].GetBigChainID() + + client := new(clientMocks.EVM) + legacyTransactor, err := signer.GetTransactor(s.GetTestContext(), legacyChainID) + s.Require().NoError(err) + + dynamicTransactor, err := signer.GetTransactor(s.GetTestContext(), dynamicChainID) + s.Require().NoError(err) + + maxGasPrice := big.NewInt(1000 * params.GWei) + minGasPrice := big.NewInt(10 * params.GWei) + cfg := &config.Config{ + Chains: map[int]config.ChainConfig{ + int(legacyChainID.Int64()): { + MinGasPrice: minGasPrice, + MaxGasPrice: maxGasPrice, + SupportsEIP1559: false, + }, + int(dynamicChainID.Int64()): { + MinGasPrice: minGasPrice, + MaxGasPrice: maxGasPrice, + SupportsEIP1559: true, + }, + }, + } + ts := submitter.NewTestTransactionSubmitter(s.metrics, signer, s, s.store, cfg) + + resetTransactors := func() { + legacyTransactor.GasPrice = nil + dynamicTransactor.GasFeeCap = nil + dynamicTransactor.GasTipCap = nil + } + + getLegacyTx := func(gasPrice *big.Int) *types.Transaction { + return types.NewTx(&types.LegacyTx{ + GasPrice: gasPrice, + }) + } + + getDynamicTx := func(gasFeeCap, gasTipCap *big.Int) *types.Transaction { + return types.NewTx(&types.DynamicFeeTx{ + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + }) + } + + s.Run("LegacyTx:FromOracle", func() { + resetTransactors() + gasPrice := big.NewInt(100 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, nil) + s.Require().NoError(err) + s.Equal(gasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + }) + + s.Run("DynamicTx:FromOracle", func() { + resetTransactors() + gasPrice := big.NewInt(120 * params.GWei) + gasTipCap := big.NewInt(50 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) + s.Require().NoError(err) + s.Equal(gasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(gasTipCap, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + }) + + s.Run("LegacyTx:BelowMin", func() { + resetTransactors() + gasPrice := big.NewInt(1 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, nil) + s.Require().NoError(err) + s.Equal(minGasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + }) + + s.Run("DynamicTx:BelowMin", func() { + resetTransactors() + gasPrice := big.NewInt(2 * params.GWei) + gasTipCap := big.NewInt(1 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) + s.Require().NoError(err) + s.Equal(minGasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(minGasPrice, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + }) + + s.Run("LegacyTx:AboveMax", func() { + resetTransactors() + gasPrice := big.NewInt(10000 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, nil) + s.NotNil(err) + }) + + s.Run("DynamicTx:AboveMax", func() { + resetTransactors() + gasPrice := big.NewInt(20000 * params.GWei) + gasTipCap := big.NewInt(10000 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) + s.NotNil(err) + }) + + s.Run("LegacyTx:SimpleBump", func() { + resetTransactors() + prevTx := getLegacyTx(big.NewInt(100 * params.GWei)) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(big.NewInt(50*params.GWei), nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) + s.Require().NoError(err) + s.Equal(big.NewInt(110*params.GWei), legacyTransactor.GasPrice, testsuite.BigIntComparer()) + }) + + s.Run("DynamicTx:SimpleBump", func() { + resetTransactors() + prevTx := getDynamicTx(big.NewInt(150*params.GWei), big.NewInt(110*params.GWei)) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(big.NewInt(70*params.GWei), nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(big.NewInt(60*params.GWei), nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) + s.Require().NoError(err) + s.Equal(big.NewInt(165*params.GWei), dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(big.NewInt(121*params.GWei), dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + }) +} + +func (s *SubmitterSuite) ATestSetGasPrice2() { + wall, err := wallet.FromRandom() + s.Require().NoError(err) + + signer := localsigner.NewSigner(wall.PrivateKey()) + chainID := s.testBackends[0].GetBigChainID() client := new(clientMocks.EVM) @@ -42,54 +177,59 @@ func (s *SubmitterSuite) TestSetGasPrice() { // 1. Test with gas price set, but not one that exceeds max (not eip-1559) gasPrice := new(big.Int).SetUint64(gofakeit.Uint64()) maxPrice := new(big.Int).Add(gasPrice, new(big.Int).SetUint64(1)) - cfg.SetGlobalMaxGasPrice(maxPrice) + s.Run("LegacyTxBelowMax", func() { + cfg.SetGlobalMaxGasPrice(maxPrice) - client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Times(3).Return(gasPrice, nil) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Times(3).Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) + s.Require().NoError(err) - s.Equal(gasPrice, transactor.GasPrice, testsuite.BigIntComparer()) + s.Equal(gasPrice, transactor.GasPrice, testsuite.BigIntComparer()) + }) // 2. Test with gas price set, but one that exceeds max, should return max (not eip-1559) - maxPrice = new(big.Int).Sub(gasPrice, new(big.Int).SetUint64(1)) - cfg.SetGlobalMaxGasPrice(maxPrice) + s.Run("SetGasPriceLegacyAboveMax", func() { + maxPrice = new(big.Int).Sub(gasPrice, new(big.Int).SetUint64(1)) + cfg.SetGlobalMaxGasPrice(maxPrice) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) - s.Equal(maxPrice, transactor.GasPrice, testsuite.BigIntComparer()) + err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) + s.NotNil(err) + }) // 3. Test with gas price set, but one that exceeds max, should return max (legacy tx) - cfg.SetGlobalEIP1559Support(true) - tipCap := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) - client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(tipCap, nil) + s.Run("SetGasPriceDynamicAboveMax", func() { + cfg.SetGlobalEIP1559Support(true) + tipCap := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(tipCap, nil) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) + err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) + s.NotNil(err) + }) - s.Equal(tipCap, transactor.GasTipCap, testsuite.BigIntComparer()) - s.Equal(maxPrice, transactor.GasFeeCap, testsuite.BigIntComparer()) + // s.Equal(tipCap, transactor.GasTipCap, testsuite.BigIntComparer()) + // s.Equal(maxPrice, transactor.GasFeeCap, testsuite.BigIntComparer()) - // 4. Test with zero gas price, should return base gas price - cfg.SetGlobalEIP1559Support(false) - minGasPrice := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) - cfg.SetMinGasPrice(minGasPrice) - gasPrice = big.NewInt(0) - client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Return(gasPrice, nil) + // // 4. Test with zero gas price, should return base gas price + // cfg.SetGlobalEIP1559Support(false) + // minGasPrice := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) + // cfg.SetMinGasPrice(minGasPrice) + // gasPrice = big.NewInt(0) + // client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Return(gasPrice, nil) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) + // err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) + // s.Require().NoError(err) - s.Equal(minGasPrice, transactor.GasPrice, testsuite.BigIntComparer()) + // s.Equal(minGasPrice, transactor.GasPrice, testsuite.BigIntComparer()) - // 5. Test with zero gas price with EIP1559, should return base gas price - cfg.SetGlobalEIP1559Support(true) - gasPrice = big.NewInt(0) - client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Return(gasPrice, nil) + // // 5. Test with zero gas price with EIP1559, should return base gas price + // cfg.SetGlobalEIP1559Support(true) + // gasPrice = big.NewInt(0) + // client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Return(gasPrice, nil) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) + // err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) + // s.Require().NoError(err) - s.Equal(minGasPrice, transactor.GasTipCap, testsuite.BigIntComparer()) + // s.Equal(minGasPrice, transactor.GasTipCap, testsuite.BigIntComparer()) // 6. Test with bump (TODO) // 7. Test with bump and max (TODO) From 9e6c08c195d7c4fe20843895ca580930d9c18e62 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 12:51:29 -0500 Subject: [PATCH 07/23] Feat: add WithOracleOverride cases --- ethergo/submitter/submitter_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index fcdd3032cb..6fd06b70a8 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -157,6 +157,29 @@ func (s *SubmitterSuite) TestSetGasPrice() { s.Equal(big.NewInt(165*params.GWei), dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) s.Equal(big.NewInt(121*params.GWei), dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) }) + + s.Run("LegacyTx:BumpWithOracleOverride", func() { + resetTransactors() + prevTx := getLegacyTx(big.NewInt(100 * params.GWei)) + gasPrice := big.NewInt(200 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) + s.Require().NoError(err) + s.Equal(gasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + }) + + s.Run("DynamicTx:BumpWithOracleOverride", func() { + resetTransactors() + prevTx := getDynamicTx(big.NewInt(150*params.GWei), big.NewInt(110*params.GWei)) + gasPrice := big.NewInt(200 * params.GWei) + gasTipCap := big.NewInt(150 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) + s.Require().NoError(err) + s.Equal(gasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(gasTipCap, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + }) } func (s *SubmitterSuite) ATestSetGasPrice2() { From c09a8c1547add909d2fb7e508f3fedbb621e7734 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 12:56:24 -0500 Subject: [PATCH 08/23] Feat: add PrevTx cases --- ethergo/submitter/submitter_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index 6fd06b70a8..30e02497c4 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -180,6 +180,29 @@ func (s *SubmitterSuite) TestSetGasPrice() { s.Equal(gasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) s.Equal(gasTipCap, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) }) + + s.Run("LegacyTx:BumpWithPrevDynamicTx", func() { + resetTransactors() + prevTx := getDynamicTx(big.NewInt(100*params.GWei), big.NewInt(80*params.GWei)) + gasPrice := big.NewInt(50 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) + s.Require().NoError(err) + s.Equal(big.NewInt(110*params.GWei), legacyTransactor.GasPrice, testsuite.BigIntComparer()) + }) + + s.Run("DynamicTx:BumpWithPrevLegacyTx", func() { + resetTransactors() + prevTx := getLegacyTx(big.NewInt(100 * params.GWei)) + gasPrice := big.NewInt(50 * params.GWei) + gasTipCap := big.NewInt(25 * params.GWei) + client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) + client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) + err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) + s.Require().NoError(err) + s.Equal(big.NewInt(110*params.GWei), dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(big.NewInt(110*params.GWei), dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + }) } func (s *SubmitterSuite) ATestSetGasPrice2() { From e2086a50f72719697a75d05d9f8e065d93d42d9f Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 13:07:01 -0500 Subject: [PATCH 09/23] Feat: add assertGasValues() helper --- ethergo/submitter/submitter_test.go | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index 30e02497c4..10aef5e936 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -78,13 +78,19 @@ func (s *SubmitterSuite) TestSetGasPrice() { }) } + assertGasValues := func(transactor *bind.TransactOpts, gasPrice, gasFeeCap, gasTipCap *big.Int) { + s.Equal(gasPrice, transactor.GasPrice, testsuite.BigIntComparer()) + s.Equal(gasFeeCap, transactor.GasFeeCap, testsuite.BigIntComparer()) + s.Equal(gasTipCap, transactor.GasTipCap, testsuite.BigIntComparer()) + } + s.Run("LegacyTx:FromOracle", func() { resetTransactors() gasPrice := big.NewInt(100 * params.GWei) client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, nil) s.Require().NoError(err) - s.Equal(gasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + assertGasValues(legacyTransactor, gasPrice, nil, nil) }) s.Run("DynamicTx:FromOracle", func() { @@ -95,8 +101,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) s.Require().NoError(err) - s.Equal(gasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) - s.Equal(gasTipCap, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + assertGasValues(dynamicTransactor, nil, gasPrice, gasTipCap) }) s.Run("LegacyTx:BelowMin", func() { @@ -105,7 +110,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, nil) s.Require().NoError(err) - s.Equal(minGasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + assertGasValues(legacyTransactor, minGasPrice, nil, nil) }) s.Run("DynamicTx:BelowMin", func() { @@ -116,8 +121,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) s.Require().NoError(err) - s.Equal(minGasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) - s.Equal(minGasPrice, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + assertGasValues(dynamicTransactor, nil, minGasPrice, minGasPrice) }) s.Run("LegacyTx:AboveMax", func() { @@ -144,7 +148,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(big.NewInt(50*params.GWei), nil) err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) s.Require().NoError(err) - s.Equal(big.NewInt(110*params.GWei), legacyTransactor.GasPrice, testsuite.BigIntComparer()) + assertGasValues(legacyTransactor, big.NewInt(110*params.GWei), nil, nil) }) s.Run("DynamicTx:SimpleBump", func() { @@ -154,8 +158,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(big.NewInt(60*params.GWei), nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) s.Require().NoError(err) - s.Equal(big.NewInt(165*params.GWei), dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) - s.Equal(big.NewInt(121*params.GWei), dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + assertGasValues(dynamicTransactor, nil, big.NewInt(165*params.GWei), big.NewInt(121*params.GWei)) }) s.Run("LegacyTx:BumpWithOracleOverride", func() { @@ -165,7 +168,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) s.Require().NoError(err) - s.Equal(gasPrice, legacyTransactor.GasPrice, testsuite.BigIntComparer()) + assertGasValues(legacyTransactor, gasPrice, nil, nil) }) s.Run("DynamicTx:BumpWithOracleOverride", func() { @@ -177,8 +180,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) s.Require().NoError(err) - s.Equal(gasPrice, dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) - s.Equal(gasTipCap, dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + assertGasValues(dynamicTransactor, nil, gasPrice, gasTipCap) }) s.Run("LegacyTx:BumpWithPrevDynamicTx", func() { @@ -188,7 +190,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) err = ts.SetGasPrice(s.GetTestContext(), client, legacyTransactor, legacyChainID, prevTx) s.Require().NoError(err) - s.Equal(big.NewInt(110*params.GWei), legacyTransactor.GasPrice, testsuite.BigIntComparer()) + assertGasValues(legacyTransactor, big.NewInt(110*params.GWei), nil, nil) }) s.Run("DynamicTx:BumpWithPrevLegacyTx", func() { @@ -200,8 +202,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, prevTx) s.Require().NoError(err) - s.Equal(big.NewInt(110*params.GWei), dynamicTransactor.GasFeeCap, testsuite.BigIntComparer()) - s.Equal(big.NewInt(110*params.GWei), dynamicTransactor.GasTipCap, testsuite.BigIntComparer()) + assertGasValues(dynamicTransactor, nil, big.NewInt(110*params.GWei), big.NewInt(110*params.GWei)) }) } From e5bbdd21879a1197149ca2e47bc3ae2b9ed83899 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 13:12:40 -0500 Subject: [PATCH 10/23] Cleanup: pass useDynamic to applyGasFloor() --- ethergo/submitter/submitter.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 78462ab2b6..70bc6fe96e 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -370,7 +370,7 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, }() t.populateGasFromPrevTx(ctx, transactor, prevTx, useDynamic) - t.applyGasFloor(ctx, transactor, chainID, shouldBump) + t.applyGasFloor(ctx, transactor, chainID, useDynamic, shouldBump) err = t.applyGasFromOracle(ctx, transactor, client, useDynamic) if err != nil { @@ -423,7 +423,7 @@ func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor // applyGasFloor applies the min gas price from the config if values are unset. // Otherwise, gas values are bumped by the configured GasBumpPercentage. -func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, shouldBump bool) { +func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic, shouldBump bool) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") defer func() { @@ -437,7 +437,6 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr }() gasFloor := t.config.GetMinGasPrice(chainID) - useDynamic := t.config.SupportsEIP1559(chainID) if shouldBump { bumpPct := t.config.GetGasBumpPercentage(chainID) if useDynamic { From 1e56c27affbac3164baf44b25edd04ae7e7eaff1 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 13:12:58 -0500 Subject: [PATCH 11/23] Feat: remove old submitter test --- ethergo/submitter/submitter_test.go | 77 ----------------------------- 1 file changed, 77 deletions(-) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index 10aef5e936..ce9f879996 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -4,7 +4,6 @@ import ( "fmt" "math/big" - "github.com/brianvoe/gofakeit/v6" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" @@ -206,82 +205,6 @@ func (s *SubmitterSuite) TestSetGasPrice() { }) } -func (s *SubmitterSuite) ATestSetGasPrice2() { - wall, err := wallet.FromRandom() - s.Require().NoError(err) - - signer := localsigner.NewSigner(wall.PrivateKey()) - - chainID := s.testBackends[0].GetBigChainID() - client := new(clientMocks.EVM) - - transactor, err := signer.GetTransactor(s.GetTestContext(), chainID) - s.Require().NoError(err) - - cfg := &config.Config{} - ts := submitter.NewTestTransactionSubmitter(s.metrics, signer, s, s.store, cfg) - - // 1. Test with gas price set, but not one that exceeds max (not eip-1559) - gasPrice := new(big.Int).SetUint64(gofakeit.Uint64()) - maxPrice := new(big.Int).Add(gasPrice, new(big.Int).SetUint64(1)) - s.Run("LegacyTxBelowMax", func() { - cfg.SetGlobalMaxGasPrice(maxPrice) - - client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Times(3).Return(gasPrice, nil) - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.Require().NoError(err) - - s.Equal(gasPrice, transactor.GasPrice, testsuite.BigIntComparer()) - }) - - // 2. Test with gas price set, but one that exceeds max, should return max (not eip-1559) - s.Run("SetGasPriceLegacyAboveMax", func() { - maxPrice = new(big.Int).Sub(gasPrice, new(big.Int).SetUint64(1)) - cfg.SetGlobalMaxGasPrice(maxPrice) - - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.NotNil(err) - }) - - // 3. Test with gas price set, but one that exceeds max, should return max (legacy tx) - s.Run("SetGasPriceDynamicAboveMax", func() { - cfg.SetGlobalEIP1559Support(true) - tipCap := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) - client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(tipCap, nil) - - err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - s.NotNil(err) - }) - - // s.Equal(tipCap, transactor.GasTipCap, testsuite.BigIntComparer()) - // s.Equal(maxPrice, transactor.GasFeeCap, testsuite.BigIntComparer()) - - // // 4. Test with zero gas price, should return base gas price - // cfg.SetGlobalEIP1559Support(false) - // minGasPrice := new(big.Int).SetUint64(uint64(gofakeit.Uint32())) - // cfg.SetMinGasPrice(minGasPrice) - // gasPrice = big.NewInt(0) - // client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Return(gasPrice, nil) - - // err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - // s.Require().NoError(err) - - // s.Equal(minGasPrice, transactor.GasPrice, testsuite.BigIntComparer()) - - // // 5. Test with zero gas price with EIP1559, should return base gas price - // cfg.SetGlobalEIP1559Support(true) - // gasPrice = big.NewInt(0) - // client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Return(gasPrice, nil) - - // err = ts.SetGasPrice(s.GetTestContext(), client, transactor, chainID, nil) - // s.Require().NoError(err) - - // s.Equal(minGasPrice, transactor.GasTipCap, testsuite.BigIntComparer()) - - // 6. Test with bump (TODO) - // 7. Test with bump and max (TODO) -} - func (s *SubmitterSuite) TestGetGasBlock() { wall, err := wallet.FromRandom() s.Require().NoError(err) From 19a4445aadb94afcc2b4369f2ba03a00e0452afe Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 13:22:14 -0500 Subject: [PATCH 12/23] Cleanup: lint --- ethergo/submitter/submitter.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 70bc6fe96e..844fff4769 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -387,12 +387,14 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, // populateGasFromPrevTx populates the gas fields from the previous transaction. // Note that in the event of a tx type mismatch, gasFeeCap is copied to gasPrice, // and gasPrice is copied to both gasFeeCap and gasTipCap in the opposite scenario. +// +//nolint:nestif func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor *bind.TransactOpts, prevTx *types.Transaction, currentDynamic bool) { if prevTx == nil { return } - ctx, span := t.metrics.Tracer().Start(ctx, "submitter.populateGasFromPrevTx") + _, span := t.metrics.Tracer().Start(ctx, "submitter.populateGasFromPrevTx") defer func() { span.SetAttributes( @@ -423,8 +425,10 @@ func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor // applyGasFloor applies the min gas price from the config if values are unset. // Otherwise, gas values are bumped by the configured GasBumpPercentage. +// +//nolint:cyclop,nestif func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic, shouldBump bool) { - ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") + _, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") defer func() { span.SetAttributes( @@ -463,19 +467,16 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr if transactor.GasTipCap == nil || transactor.GasTipCap.Cmp(gasFloor) < 0 { transactor.GasTipCap = gasFloor } - } else { - if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { - transactor.GasPrice = gasFloor - } + } else if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { + transactor.GasPrice = gasFloor } } - return } // applyGasFromOracle fetches gas values from a RPC endpoint and attempts to set them. // If values are already specified, they will be overridden if the oracle values are higher. func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bind.TransactOpts, client client.EVM, useDynamic bool) (err error) { - ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") + ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFromOracle") defer func() { metrics.EndSpanWithErr(span, err) @@ -515,7 +516,7 @@ func (t *txSubmitterImpl) applyGasFromOracle(ctx context.Context, transactor *bi // applyGasCeil evaluates current gas values versus the configured maximum, and // returns an error if they exceed the maximum. func (t *txSubmitterImpl) applyGasCeil(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic bool) (err error) { - ctx, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") + _, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasCeil") maxPrice := t.config.GetMaxGasPrice(chainID) From 6c52b8b698982134f37797897eb9fb8e63577264 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 14:38:21 -0500 Subject: [PATCH 13/23] [goreleaser] From d245a735186ad8f6d12aeba5950b98198c5ca2bf Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 15:12:32 -0500 Subject: [PATCH 14/23] Cleanup: populateFromPrevTx() -> bumpFromPrevTx() --- ethergo/chain/gas/cmp.go | 3 ++ ethergo/submitter/submitter.go | 64 +++++++++++----------------------- 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/ethergo/chain/gas/cmp.go b/ethergo/chain/gas/cmp.go index 2ca13ef56d..30bf20eccd 100644 --- a/ethergo/chain/gas/cmp.go +++ b/ethergo/chain/gas/cmp.go @@ -106,6 +106,9 @@ func bumpDynamicTxFees(opts *bind.TransactOpts, percentIncrease int, baseFee, ma // BumpByPercent bumps a gas price by a percentage. func BumpByPercent(gasPrice *big.Int, percentIncrease int) *big.Int { + if gasPrice == nil { + return nil + } price := core.CopyBigInt(gasPrice) calculatedGasPrice := big.NewFloat(0).Mul(big.NewFloat(1+0.01*float64(percentIncrease)), big.NewFloat(0).SetInt(price)) price, _ = calculatedGasPrice.Int(price) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 844fff4769..a7fefb73da 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -355,13 +355,11 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, chainID := int(bigChainID.Uint64()) useDynamic := t.config.SupportsEIP1559(chainID) - shouldBump := prevTx != nil defer func() { span.SetAttributes( attribute.Int(metrics.ChainID, chainID), attribute.Bool("use_dynamic", useDynamic), - attribute.Bool("should_bump", shouldBump), attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), @@ -369,8 +367,8 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, metrics.EndSpanWithErr(span, err) }() - t.populateGasFromPrevTx(ctx, transactor, prevTx, useDynamic) - t.applyGasFloor(ctx, transactor, chainID, useDynamic, shouldBump) + t.bumpGasFromPrevTx(ctx, transactor, prevTx, chainID, useDynamic) + t.applyGasFloor(ctx, transactor, chainID, useDynamic) err = t.applyGasFromOracle(ctx, transactor, client, useDynamic) if err != nil { @@ -384,17 +382,18 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, return nil } -// populateGasFromPrevTx populates the gas fields from the previous transaction. +// bumpGasFromPrevTx populates the gas fields from the previous transaction and bumps +// the appropriate values corresponding to the configured GasBumpPercentage. // Note that in the event of a tx type mismatch, gasFeeCap is copied to gasPrice, // and gasPrice is copied to both gasFeeCap and gasTipCap in the opposite scenario. // //nolint:nestif -func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor *bind.TransactOpts, prevTx *types.Transaction, currentDynamic bool) { +func (t *txSubmitterImpl) bumpGasFromPrevTx(ctx context.Context, transactor *bind.TransactOpts, prevTx *types.Transaction, chainID int, currentDynamic bool) { if prevTx == nil { return } - _, span := t.metrics.Tracer().Start(ctx, "submitter.populateGasFromPrevTx") + _, span := t.metrics.Tracer().Start(ctx, "submitter.bumpGasFromPrevTx") defer func() { span.SetAttributes( @@ -406,28 +405,28 @@ func (t *txSubmitterImpl) populateGasFromPrevTx(ctx context.Context, transactor }() prevDynamic := prevTx.Type() == types.DynamicFeeTxType + bumpPct := t.config.GetGasBumpPercentage(chainID) if currentDynamic { if prevDynamic { - transactor.GasFeeCap = core.CopyBigInt(prevTx.GasFeeCap()) - transactor.GasTipCap = core.CopyBigInt(prevTx.GasTipCap()) + transactor.GasFeeCap = gas.BumpByPercent(core.CopyBigInt(prevTx.GasFeeCap()), bumpPct) + transactor.GasTipCap = gas.BumpByPercent(core.CopyBigInt(prevTx.GasTipCap()), bumpPct) } else { - transactor.GasFeeCap = core.CopyBigInt(prevTx.GasPrice()) - transactor.GasTipCap = core.CopyBigInt(prevTx.GasPrice()) + transactor.GasFeeCap = gas.BumpByPercent(core.CopyBigInt(prevTx.GasPrice()), bumpPct) + transactor.GasTipCap = gas.BumpByPercent(core.CopyBigInt(prevTx.GasPrice()), bumpPct) } } else { if prevDynamic { - transactor.GasPrice = core.CopyBigInt(prevTx.GasFeeCap()) + transactor.GasPrice = gas.BumpByPercent(core.CopyBigInt(prevTx.GasFeeCap()), bumpPct) } else { - transactor.GasPrice = core.CopyBigInt(prevTx.GasPrice()) + transactor.GasPrice = gas.BumpByPercent(core.CopyBigInt(prevTx.GasPrice()), bumpPct) } } } // applyGasFloor applies the min gas price from the config if values are unset. -// Otherwise, gas values are bumped by the configured GasBumpPercentage. // //nolint:cyclop,nestif -func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic, shouldBump bool) { +func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.TransactOpts, chainID int, useDynamic bool) { _, span := t.metrics.Tracer().Start(ctx, "submitter.applyGasFloor") defer func() { @@ -435,41 +434,20 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr attribute.String("gas_price", bigPtrToString(transactor.GasPrice)), attribute.String("gas_fee_cap", bigPtrToString(transactor.GasFeeCap)), attribute.String("gas_tip_cap", bigPtrToString(transactor.GasTipCap)), - attribute.Bool("should_bump", shouldBump), ) metrics.EndSpan(span) }() gasFloor := t.config.GetMinGasPrice(chainID) - if shouldBump { - bumpPct := t.config.GetGasBumpPercentage(chainID) - if useDynamic { - if transactor.GasFeeCap == nil { - transactor.GasFeeCap = gasFloor - span.AddEvent("gas fee cap is nil; setting to gas floor") - } else { - transactor.GasFeeCap = gas.BumpByPercent(transactor.GasFeeCap, bumpPct) - } - if transactor.GasTipCap == nil { - transactor.GasTipCap = gasFloor - span.AddEvent("gas tip cap is nil; setting to gas floor") - } else { - transactor.GasTipCap = gas.BumpByPercent(transactor.GasTipCap, bumpPct) - } - } else { - transactor.GasPrice = gas.BumpByPercent(transactor.GasPrice, bumpPct) + if useDynamic { + if transactor.GasFeeCap == nil || transactor.GasFeeCap.Cmp(gasFloor) < 0 { + transactor.GasFeeCap = gasFloor } - } else { - if useDynamic { - if transactor.GasFeeCap == nil || transactor.GasFeeCap.Cmp(gasFloor) < 0 { - transactor.GasFeeCap = gasFloor - } - if transactor.GasTipCap == nil || transactor.GasTipCap.Cmp(gasFloor) < 0 { - transactor.GasTipCap = gasFloor - } - } else if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { - transactor.GasPrice = gasFloor + if transactor.GasTipCap == nil || transactor.GasTipCap.Cmp(gasFloor) < 0 { + transactor.GasTipCap = gasFloor } + } else if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { + transactor.GasPrice = gasFloor } } From b4394d1df4d201917205b8bd64b9beb7ea127ec6 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 15:20:38 -0500 Subject: [PATCH 15/23] Feat: cap GasTipCap by GasFeeCap --- ethergo/submitter/submitter.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index a7fefb73da..99242af83d 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -507,7 +507,10 @@ func (t *txSubmitterImpl) applyGasCeil(ctx context.Context, transactor *bind.Tra if transactor.GasFeeCap.Cmp(maxPrice) > 0 { return fmt.Errorf("gas fee cap %s exceeds max price %s", transactor.GasFeeCap, maxPrice) } - // TODO: should maxPrice apply to GasTipCap as well? + if transactor.GasTipCap.Cmp(transactor.GasFeeCap) > 0 { + transactor.GasTipCap = core.CopyBigInt(transactor.GasFeeCap) + span.AddEvent("tip cap exceeds fee cap; setting tip cap to fee cap") + } } else { if transactor.GasPrice.Cmp(maxPrice) > 0 { return fmt.Errorf("gas price %s exceeds max price %s", transactor.GasPrice, maxPrice) From 5250e953ca97bf8ca75b66d463381f440c4ddd07 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 15:20:41 -0500 Subject: [PATCH 16/23] [goreleaser] From fddb1a82f3592c722efdf40b58b90800f150af1d Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 16:22:03 -0500 Subject: [PATCH 17/23] Feat: default min gas price to 1 gwei --- ethergo/submitter/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethergo/submitter/config/config.go b/ethergo/submitter/config/config.go index c0e90cdfdd..b4b96f66cf 100644 --- a/ethergo/submitter/config/config.go +++ b/ethergo/submitter/config/config.go @@ -68,7 +68,7 @@ const ( var DefaultMaxPrice = big.NewInt(500 * params.GWei) // DefaultMinGasPrice is the default min price of a tx. -var DefaultMinGasPrice = big.NewInt(10 * params.GWei) +var DefaultMinGasPrice = big.NewInt(1 * params.GWei) // note: there's probably a way to clean these getters up with generics, the real problem comes with the fact that // that this would require the caller to override the entire struct, which is not ideal.. From 3cb6dae128f6f926ef7a3877af3989a737b286f5 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 16:22:04 -0500 Subject: [PATCH 18/23] [goreleaser] From e1e069561effd146a49100694118c57479bb984c Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 18:40:58 -0500 Subject: [PATCH 19/23] Feat: add minTipCap var --- ethergo/submitter/submitter.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 99242af83d..4b2302f237 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" "github.com/ipfs/go-log" "github.com/synapsecns/sanguine/core" "github.com/synapsecns/sanguine/core/mapmutex" @@ -423,6 +424,8 @@ func (t *txSubmitterImpl) bumpGasFromPrevTx(ctx context.Context, transactor *bin } } +var minTipCap = big.NewInt(1 * params.Wei) + // applyGasFloor applies the min gas price from the config if values are unset. // //nolint:cyclop,nestif @@ -444,7 +447,7 @@ func (t *txSubmitterImpl) applyGasFloor(ctx context.Context, transactor *bind.Tr transactor.GasFeeCap = gasFloor } if transactor.GasTipCap == nil || transactor.GasTipCap.Cmp(gasFloor) < 0 { - transactor.GasTipCap = gasFloor + transactor.GasTipCap = minTipCap } } else if transactor.GasPrice == nil || transactor.GasPrice.Cmp(gasFloor) < 0 { transactor.GasPrice = gasFloor From 25b93456f8d6bf3791aa26f991b09973fca2db50 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 18:41:59 -0500 Subject: [PATCH 20/23] Fix: minTipCap = 10 wei --- ethergo/submitter/submitter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 4b2302f237..a919b3a6dd 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -424,7 +424,7 @@ func (t *txSubmitterImpl) bumpGasFromPrevTx(ctx context.Context, transactor *bin } } -var minTipCap = big.NewInt(1 * params.Wei) +var minTipCap = big.NewInt(10 * params.Wei) // applyGasFloor applies the min gas price from the config if values are unset. // From ed148a06322e481e4d32cded12c6313220f76530 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 18:54:16 -0500 Subject: [PATCH 21/23] Cleanup: comment --- ethergo/submitter/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethergo/submitter/config/config.go b/ethergo/submitter/config/config.go index b4b96f66cf..cbb4f91de7 100644 --- a/ethergo/submitter/config/config.go +++ b/ethergo/submitter/config/config.go @@ -110,7 +110,7 @@ func (c *Config) GetMaxGasPrice(chainID int) (maxPrice *big.Int) { return } -// GetMinGasPrice returns the maximum gas price to use for transactions. +// GetMinGasPrice returns the minimum gas price to use for transactions. func (c *Config) GetMinGasPrice(chainID int) (minPrice *big.Int) { minPrice = c.MinGasPrice From de10984fb113018ef1b194f298edeb9897cafa37 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 18:54:18 -0500 Subject: [PATCH 22/23] [goreleaser] From a4057c554346f2101e389b8ebb431941b80ea518 Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Fri, 5 Apr 2024 19:33:25 -0500 Subject: [PATCH 23/23] Fix: test --- ethergo/submitter/submitter_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethergo/submitter/submitter_test.go b/ethergo/submitter/submitter_test.go index ce9f879996..b95578bc11 100644 --- a/ethergo/submitter/submitter_test.go +++ b/ethergo/submitter/submitter_test.go @@ -41,7 +41,7 @@ func (s *SubmitterSuite) TestSetGasPrice() { s.Require().NoError(err) maxGasPrice := big.NewInt(1000 * params.GWei) - minGasPrice := big.NewInt(10 * params.GWei) + minGasPrice := big.NewInt(1 * params.GWei) cfg := &config.Config{ Chains: map[int]config.ChainConfig{ int(legacyChainID.Int64()): { @@ -114,13 +114,13 @@ func (s *SubmitterSuite) TestSetGasPrice() { s.Run("DynamicTx:BelowMin", func() { resetTransactors() - gasPrice := big.NewInt(2 * params.GWei) - gasTipCap := big.NewInt(1 * params.GWei) + gasPrice := big.NewInt(0.5 * params.GWei) + gasTipCap := big.NewInt(0) client.On(testsuite.GetFunctionName(client.SuggestGasPrice), mock.Anything).Once().Return(gasPrice, nil) client.On(testsuite.GetFunctionName(client.SuggestGasTipCap), mock.Anything).Once().Return(gasTipCap, nil) err = ts.SetGasPrice(s.GetTestContext(), client, dynamicTransactor, dynamicChainID, nil) s.Require().NoError(err) - assertGasValues(dynamicTransactor, nil, minGasPrice, minGasPrice) + assertGasValues(dynamicTransactor, nil, minGasPrice, big.NewInt(10*params.Wei)) }) s.Run("LegacyTx:AboveMax", func() {