Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+dynamic_gas_unit_add_percentage flag #3494

Merged
merged 42 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
dfbf6ba
+dynamic_gas_unit_add_percentage flag
parodime Jan 23, 2025
93459f1
test fix
parodime Jan 24, 2025
905a3a5
[goreleaser]
parodime Jan 24, 2025
09816fb
new simulate approach
parodime Jan 24, 2025
63f730c
[goreleaser]
parodime Jan 24, 2025
31ca3cf
fix tx.Hash empty [goreleaser]
parodime Jan 24, 2025
d8481f2
remove debug noise. nil deref fix... ?
parodime Jan 24, 2025
d7f1cad
[goreleaser]
parodime Jan 24, 2025
3d7eea2
check tx call b4 estgas [goreleaser]
parodime Jan 24, 2025
4c11d33
+tmp debuggers [goreleaser]
parodime Jan 27, 2025
145583d
more tmp debug [goreleaser]
parodime Jan 27, 2025
2005d91
tmp debug tx output [goreleaser]
parodime Jan 27, 2025
a8a48bb
tmp debug submit tweaks [goreleaser]
parodime Jan 27, 2025
75c9c44
submitTransaction refactor [goreleaser]
parodime Jan 27, 2025
96e16c3
clone transactor [goreleaser]
parodime Jan 27, 2025
dada2b0
deepcopy [goreleaser]
parodime Jan 27, 2025
7abfdb0
[goreleaser]
parodime Jan 27, 2025
0e7c236
test getGasEstimate skip
parodime Jan 27, 2025
220e0d4
[goreleaser]
parodime Jan 27, 2025
b995385
try gaslimit 0 [goreleaser]
parodime Jan 28, 2025
4782b44
gaslimit2 [goreleaser]
parodime Jan 28, 2025
d699cd0
gaslimit2 pre/post [goreleaser]
parodime Jan 28, 2025
04ccdc2
tx_forGasEst [goreleaser]
parodime Jan 28, 2025
c8f2dfe
diff nonces [goreleaser]
parodime Jan 28, 2025
d199850
Prove gas [goreleaser]
parodime Jan 28, 2025
e8fd10e
print nonce [goreleaser]
parodime Jan 28, 2025
ee9eb85
low gas test [goreleaser]
parodime Jan 28, 2025
f6bfa43
getGasEst bump approach [goreleaser]
parodime Jan 28, 2025
c79a81b
reproduce [goreleaser]
parodime Jan 28, 2025
82b4f99
repro err [goreleaser]
parodime Jan 28, 2025
5b02cca
bump approach [goreleaser]
parodime Jan 28, 2025
965802d
bump approach - arbi test focus [goreleaser]
parodime Jan 29, 2025
7b62df2
swap context [goreleaser]
parodime Jan 29, 2025
73442fa
fix transactor_forGasEstimate lock. +QuoteDetails event
parodime Jan 31, 2025
ab18ea9
quotedetails event fix. +basic print logs
parodime Jan 31, 2025
cf43fdc
print log impvs [goreleaser]
parodime Jan 31, 2025
c24c568
typo fix
parodime Jan 31, 2025
0e35f40
gitignore edit
parodime Jan 31, 2025
8adb278
getGasEstimate code simplify
parodime Jan 31, 2025
961fbfc
remove temp tests
parodime Jan 31, 2025
6586d73
remove underscores, FormatError util func,
parodime Jan 31, 2025
528839f
submitTransaction use common performSignature func for sim & actual
parodime Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/bridge/docs/06-Services/04-Submitter.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ submitter_config:
dynamic_gas_estimate: true
# SupportsEIP1559 is whether or not this chain supports EIP1559.
supports_eip_1559: true
# DynamicGasUnitAddPercentage - increase gas unit limit (ie: "gas" field on a typical tx) by X% from what dynamic gas estimate returns
# Has no effect if dynamic gas estimation is not also enabled.
dynamic_gas_unit_add_percentage: 5
43114:
max_gas_price: 100000000000 # 100 Gwei
10:
Expand Down
28 changes: 26 additions & 2 deletions ethergo/submitter/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
DynamicGasEstimate bool `yaml:"dynamic_gas_estimate"`
// SupportsEIP1559 is whether or not this chain supports EIP1559
SupportsEIP1559 bool `yaml:"supports_eip_1559"`
// DynamicGasUnitAddPercentage - increase gas unit limit (ie: "gas" field on a typical tx) by X% from what dynamic gas estimate returns
// Has no effect if dynamic gas estimation is not also enabled.
DynamicGasUnitAddPercentage int `yaml:"dynamic_gas_unit_add_percentage"`
}

const (
Expand All @@ -64,6 +67,9 @@

// DefaultGasEstimate is the default gas estimate to use for transactions.
DefaultGasEstimate = uint64(1200000)

// DefaultDynamicGasUnitAddPercentage is the default percentage to bump the gas limit by.
DefaultDynamicGasUnitAddPercentage = 5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we don't want to default to zero? This is fine with me, just making sure since may not be obvious to others

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with zaps we're going to need to start doing dynamic estimates all the time and relying on the simulation to give us enough limit. a small boost by default on top of the simulation is a good idea just to further reduce chance of OOG

also -- our flat limits that we use today, by comparison, give us a boost of like +5000% so +5% is pretty small by that measure

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, most wallets are using a 50% buffer on top of the estimated gas limit. So I'd recommend increasing the default value a bit here.

)

// DefaultMaxPrice is the default max price of a tx.
Expand Down Expand Up @@ -188,19 +194,37 @@
return gasBumpPercentage
}

// GetDynamicGasUnitAddPercentage returns the percentage to bump the gas limit by

Check failure on line 197 in ethergo/submitter/config/config.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

Comment should end in a period (godot)
func (c *Config) GetDynamicGasUnitAddPercentage(chainID int) (dynamicGasUnitAddPercentage int) {
chainConfig, ok := c.Chains[chainID]
if ok {
dynamicGasUnitAddPercentage = chainConfig.DynamicGasUnitAddPercentage
}

Check warning on line 202 in ethergo/submitter/config/config.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/config/config.go#L198-L202

Added lines #L198 - L202 were not covered by tests
// if dynamicGasUnitAddPercentage is not set for the chain, use the global config
if dynamicGasUnitAddPercentage == 0 {
dynamicGasUnitAddPercentage = c.DynamicGasUnitAddPercentage
}

Check warning on line 206 in ethergo/submitter/config/config.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/config/config.go#L204-L206

Added lines #L204 - L206 were not covered by tests

// if the dynamicGasUnitAddPercentage isn't set at all, use the default
if dynamicGasUnitAddPercentage == 0 {
dynamicGasUnitAddPercentage = DefaultDynamicGasUnitAddPercentage
}
return dynamicGasUnitAddPercentage

Check warning on line 212 in ethergo/submitter/config/config.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/config/config.go#L209-L212

Added lines #L209 - L212 were not covered by tests
}

// GetGasEstimate returns the gas estimate to use for transactions
// TODO: test this method.
func (c *Config) GetGasEstimate(chainID int) (gasEstimate uint64) {
chainConfig, ok := c.Chains[chainID]
if ok {
gasEstimate = chainConfig.GasEstimate
}
// if gasBumpPercentage is not set for the chain, use the global config
// if gasEstimate is not set for the chain, use the global config
if gasEstimate == 0 {
gasEstimate = c.GasEstimate
}

// if the gasBumpPercentage isn't set at all, use the default
// if the gasEstimate isn't set at all, use the default
if gasEstimate == 0 {
gasEstimate = DefaultGasEstimate
}
Expand Down
2 changes: 2 additions & 0 deletions ethergo/submitter/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ gas_bump_percentage: 10
gas_estimate: 1000
is_l2: true
dynamic_gas_estimate: true
dynamic_gas_unit_add_percentage: 20
supports_eip_1559: true`
var cfg config.Config
err := yaml.Unmarshal([]byte(cfgStr), &cfg)
assert.NoError(t, err)
assert.Equal(t, big.NewInt(250000000000), cfg.MaxGasPrice)
assert.Equal(t, 60, cfg.BumpIntervalSeconds)
assert.Equal(t, 10, cfg.GasBumpPercentage)
assert.Equal(t, 20, cfg.DynamicGasUnitAddPercentage)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance test coverage for the new configuration parameter.

While the basic YAML parsing test is good, consider adding the following test cases:

  1. Add a test case in TestGetters for GetDynamicGasUnitAddPercentage
  2. Test the default value (5%)
  3. Add validation tests for edge cases (negative values, zero, etc.)

Here's a suggested implementation:

 func TestGetters(t *testing.T) {
     cfg := config.Config{
         ChainConfig: config.ChainConfig{
             MaxBatchSize: 5,
             DoNotBatch:   false,
             MaxGasPrice:  big.NewInt(250 * params.GWei),
+            DynamicGasUnitAddPercentage: 15,
         },
         Chains: map[int]config.ChainConfig{
                 MaxBatchSize: 8,
                 DoNotBatch:   true,
                 MaxGasPrice:  big.NewInt(300 * params.GWei),
+                DynamicGasUnitAddPercentage: 25,
             },
                 MaxBatchSize: 0, // Should use global config value
             },
         },
     }

     // ... existing test cases ...

+    t.Run("GetDynamicGasUnitAddPercentage", func(t *testing.T) {
+        // Test chain-specific value
+        assert.Equal(t, 25, cfg.GetDynamicGasUnitAddPercentage(1))
+        // Test fallback to global value
+        assert.Equal(t, 15, cfg.GetDynamicGasUnitAddPercentage(2))
+        // Test nonexistent chain
+        assert.Equal(t, 15, cfg.GetDynamicGasUnitAddPercentage(999))
+
+        // Test default value
+        emptyCfg := config.Config{}
+        assert.Equal(t, config.DefaultDynamicGasUnitAddPercentage, 
+            emptyCfg.GetDynamicGasUnitAddPercentage(1))
+
+        // Test validation (if implemented)
+        invalidCfg := config.Config{
+            ChainConfig: config.ChainConfig{
+                DynamicGasUnitAddPercentage: -1,
+            },
+        }
+        assert.Equal(t, config.DefaultDynamicGasUnitAddPercentage,
+            invalidCfg.GetDynamicGasUnitAddPercentage(1))
+    })
 }

Committable suggestion skipped: line range outside the PR's diff.

assert.Equal(t, uint64(1000), cfg.GasEstimate)
assert.Equal(t, true, cfg.DynamicGasEstimate)
assert.Equal(t, true, cfg.SupportsEIP1559(0))
Expand Down
2 changes: 2 additions & 0 deletions ethergo/submitter/config/iconfig_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 29 additions & 9 deletions ethergo/submitter/submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,6 @@
if err != nil {
span.AddEvent("could not set gas price", trace.WithAttributes(attribute.String("error", err.Error())))
}
if !t.config.GetDynamicGasEstimate(int(chainID.Uint64())) {
transactor.GasLimit = t.config.GetGasEstimate(int(chainID.Uint64()))
}

transactor.Signer = func(address common.Address, transaction *types.Transaction) (_ *types.Transaction, err error) {
locker = t.nonceMux.Lock(chainID)
Expand All @@ -421,9 +418,27 @@
//nolint: wrapcheck
return parentTransactor.Signer(address, transaction)
}

transactor.NoSend = true

tx_forEstimate, err := call(transactor)

Check failure on line 424 in ethergo/submitter/submitter.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

var-naming: don't use underscores in Go names; var tx_forEstimate should be txForEstimate (revive)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Follow Go naming conventions

The variable name tx_forEstimate uses underscores which is against Go naming conventions.

-	tx_forEstimate, err := call(transactor)
+	txForEstimate, err := call(transactor)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tx_forEstimate, err := call(transactor)
txForEstimate, err := call(transactor)
🧰 Tools
🪛 GitHub Check: Lint (ethergo)

[failure] 424-424:
var-naming: don't use underscores in Go names; var tx_forEstimate should be txForEstimate (revive)

if err != nil {
return 0, fmt.Errorf("err contract call sim: %w", err)
}

gasEstimate, err := t.getGasEstimate(ctx, chainClient, int(chainID.Uint64()), tx_forEstimate)

Check failure on line 429 in ethergo/submitter/submitter.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

G115: integer overflow conversion uint64 -> int (gosec)
parodime marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return 0, fmt.Errorf("err getGasEstimate: %w", err)
}

transactor.GasLimit = gasEstimate

transactor.NoSend = false

tx, err := call(transactor)

if err != nil {
return 0, fmt.Errorf("could not call contract: %w", err)
return 0, fmt.Errorf("err contract call exec: %w", err)
}
defer locker.Unlock()

Expand Down Expand Up @@ -677,13 +692,20 @@
// getGasEstimate gets the gas estimate for the given transaction.
// TODO: handle l2s w/ custom gas pricing through contracts.
func (t *txSubmitterImpl) getGasEstimate(ctx context.Context, chainClient client.EVM, chainID int, tx *types.Transaction) (gasEstimate uint64, err error) {

// if dynamic gas estimation is not enabled, use cfg var gas_estimate as a default
if !t.config.GetDynamicGasEstimate(chainID) {
return t.config.GetGasEstimate(chainID), nil
}

gasUnitAddPercentage := t.config.GetDynamicGasUnitAddPercentage(chainID)

Check warning on line 702 in ethergo/submitter/submitter.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/submitter.go#L701-L702

Added lines #L701 - L702 were not covered by tests
ctx, span := t.metrics.Tracer().Start(ctx, "submitter.getGasEstimate", trace.WithAttributes(
attribute.Int(metrics.ChainID, chainID),

attribute.String(metrics.TxHash, tx.Hash().String()),

attribute.Int("gasUnitAddPercentage", gasUnitAddPercentage),

Check warning on line 708 in ethergo/submitter/submitter.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/submitter.go#L708

Added line #L708 was not covered by tests
))

defer func() {
Expand All @@ -696,20 +718,18 @@
if err != nil {
return 0, fmt.Errorf("could not convert tx to call: %w", err)
}
// tmpdebug
fmt.Printf("Debug Calling EstimateGas")

gasEstimate, err = chainClient.EstimateGas(ctx, *call)
if err != nil {
span.AddEvent("could not estimate gas", trace.WithAttributes(attribute.String("error", err.Error())))

// tmpdebug
fmt.Printf("Debug Default Gas Estimate: %d\n", t.config.GetGasEstimate(chainID))

// fallback to default
return t.config.GetGasEstimate(chainID), nil
}

// Modify the gasEstimate by the configured percentage
gasEstimate = gasEstimate + (gasEstimate * uint64(gasUnitAddPercentage) / 100)

Check failure on line 731 in ethergo/submitter/submitter.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

assignOp: replace `gasEstimate = gasEstimate + (gasEstimate * uint64(gasUnitAddPercentage) / 100)` with `gasEstimate += (gasEstimate * uint64(gasUnitAddPercentage) / 100)` (gocritic)

Check warning on line 732 in ethergo/submitter/submitter.go

View check run for this annotation

Codecov / codecov/patch

ethergo/submitter/submitter.go#L731-L732

Added lines #L731 - L732 were not covered by tests
parodime marked this conversation as resolved.
Show resolved Hide resolved
return gasEstimate, nil
}

Expand Down
15 changes: 15 additions & 0 deletions ethergo/submitter/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,21 @@
}
}

func (s *SubmitterSuite) TestOpStackGas() {

Check failure on line 201 in ethergo/submitter/util_test.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

unnecessary leading newline (whitespace)

mockTx := mocks.GetMockTxes(s.GetTestContext(), s.T(), 1, types.LegacyTxType)[0]

fmt.Printf("Original Transaction Gas Limit: %d\n", mockTx.Gas())

}

Check failure on line 207 in ethergo/submitter/util_test.go

View workflow job for this annotation

GitHub Actions / Lint (ethergo)

unnecessary trailing newline (whitespace)

func TestBox(t *testing.T) {
const testTxCount = 10
mockTx := mocks.GetMockTxes(context.Background(), t, testTxCount, 0)

fmt.Printf("Original Transaction Gas Limit: %d\n", mockTx[0].Gas())
}
parodime marked this conversation as resolved.
Show resolved Hide resolved

// Test for the outersection function.
func TestOutersection(t *testing.T) {
set := []*big.Int{
Expand Down
14 changes: 14 additions & 0 deletions services/rfq/relayer/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
gasAmount := big.NewInt(0)
var err error

//tmpdebug

Check failure on line 77 in services/rfq/relayer/chain/chain.go

View workflow job for this annotation

GitHub Actions / Lint (services/rfq)

commentFormatting: put a space between `//` and comment text (gocritic)
parodime marked this conversation as resolved.
Show resolved Hide resolved
fmt.Println("SubmitRelay>start: ", request.OriginTxHash)
parodime marked this conversation as resolved.
Show resolved Hide resolved

// Check to see if ETH should be sent to destination
if util.IsGasToken(request.Transaction.DestToken) {
gasAmount = request.Transaction.DestAmount
Expand All @@ -86,19 +89,30 @@
}
}

//tmpdebug

Check failure on line 92 in services/rfq/relayer/chain/chain.go

View workflow job for this annotation

GitHub Actions / Lint (services/rfq)

commentFormatting: put a space between `//` and comment text (gocritic)
fmt.Println("SubmitRelay>SubmitTransaction: ", request.OriginTxHash)

nonce, err := c.SubmitTransaction(ctx, func(transactor *bind.TransactOpts) (tx *types.Transaction, err error) {
transactor.Value = core.CopyBigInt(gasAmount)

//tmpdebug

Check failure on line 98 in services/rfq/relayer/chain/chain.go

View workflow job for this annotation

GitHub Actions / Lint (services/rfq)

commentFormatting: put a space between `//` and comment text (gocritic)
fmt.Println("SubmitTransaction>RelayV2: ", request.OriginTxHash)

tx, err = c.Bridge.RelayV2(transactor, request.RawRequest, c.submitter.Address())
if err != nil {
return nil, fmt.Errorf("could not relay: %w", err)
}

//tmpdebug
fmt.Println("RelayV2 hash: ", tx.Hash())

return tx, nil
})
if err != nil {
return 0, nil, fmt.Errorf("could not submit transaction: %w", err)
}
//tmpdebug
fmt.Println("SubmitRelay nonce:", nonce, "gas amount:", gasAmount)

return nonce, gasAmount, nil
}
9 changes: 0 additions & 9 deletions services/rfq/relayer/quoter/quoter.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,28 +693,19 @@ func (m *Manager) generateQuote(ctx context.Context, input QuoteInput) (quote *m
return nil, fmt.Errorf("error getting total fee: %w", err)
}

// tmpdebug
fmt.Printf("Debug Total Fee Amt: %s\n", fee.String())

originRFQAddr, err := m.config.GetRFQAddress(input.OriginChainID)
if err != nil {
logger.Error("Error getting RFQ address", "error", err)
return nil, fmt.Errorf("error getting RFQ address: %w", err)
}

// tmpdebug
fmt.Printf("Debug originRFQAddr: %s\n", originRFQAddr.String())

// Build the quote
destAmount, err := m.getDestAmount(ctx, originAmount, destToken, input)
if err != nil {
logger.Error("Error getting dest amount", "error", err)
return nil, fmt.Errorf("error getting dest amount: %w", err)
}

// tmpdebug
fmt.Printf("Debug destAmount: %s\n", destAmount.String())

quote = &model.PutRelayerQuoteRequest{
OriginChainID: input.OriginChainID,
OriginTokenAddr: input.OriginTokenAddr.Hex(),
Expand Down
8 changes: 8 additions & 0 deletions services/rfq/relayer/service/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ func (q *QuoteRequestHandler) handleCommitPending(ctx context.Context, span trac
// This is the fourth step in the bridge process. Here we submit the relay transaction to the destination chain.
// TODO: just to be safe, we should probably check if another relayer has already relayed this.
func (q *QuoteRequestHandler) handleCommitConfirmed(ctx context.Context, span trace.Span, request reldb.QuoteRequest) (err error) {

//tmpdebug
fmt.Println("handleCommitConfirmed>SubmitRelay: ", request.OriginTxHash)

// TODO: store the dest txhash connected to the nonce
nonce, _, err := q.Dest.SubmitRelay(ctx, request)
if err != nil {
Expand All @@ -384,11 +388,15 @@ func (q *QuoteRequestHandler) handleCommitConfirmed(ctx context.Context, span tr
span.AddEvent("relay successfully submitted")
span.SetAttributes(attribute.Int("relay_nonce", int(nonce)))

//tmpdebug
fmt.Println("handleCommitConfirmed>UpdateQuoteRequestStatus: ", request.OriginTxHash)
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted, &request.Status)
if err != nil {
return fmt.Errorf("could not update quote request status: %w", err)
}

//tmpdebug
fmt.Println("handleCommitConfirmed>UpdateRelayNonce: ", request.OriginTxHash)
err = q.db.UpdateRelayNonce(ctx, request.TransactionID, nonce)
if err != nil {
return fmt.Errorf("could not update relay nonce: %w", err)
Expand Down
Loading