This repository has been archived by the owner on Sep 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
[TT-1490] add gas bumping #40
Merged
Merged
Changes from 8 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
8a67dd6
working gas bumping for contract deployment and inside Decode()
Tofel 19a46a1
update readme, move bumping strategy function to config, add to builder
Tofel 20b6ea3
rename config builder to client builder, fix tests which copy config
Tofel 76afc61
add tests for max gas, make each test use a different key, so they ar…
Tofel b2e9eea
synchornise test cleanup to avoid races in tests
Tofel 5d52821
streamlining + added untested support for blob/access list transactio…
Tofel 5790af8
simplify gas bumping tests, small streamlines + readme updates
Tofel 9d5ffdc
fix api tests
Tofel eec5755
CR changes
Tofel 01b8316
Merge branch 'master' into tt_1490_gas_bumping
Tofel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Gas bumping tests | ||
on: | ||
push: | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
network: [ Geth ] | ||
env: | ||
SETH_ROOT_PRIVATE_KEY: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | ||
steps: | ||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 | ||
- uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26 | ||
with: | ||
nix_path: nixpkgs=channel:nixos-unstable | ||
- name: Run tests | ||
env: | ||
SETH_NETWORK: ${{ matrix.network }} | ||
run: | | ||
nix develop -c make $SETH_NETWORK && make SETH_LOG_LEVEL=debug root_private_key=$SETH_ROOT_PRIVATE_KEY network=$SETH_NETWORK test_gas_bumping |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,24 +12,25 @@ Reliable and debug-friendly Ethereum client | |
# Content | ||
1. [Goals](#goals) | ||
2. [Features](#features) | ||
2. [Examples](#examples) | ||
3. [Setup](#setup) | ||
4. [Building test contracts](#building-test-contracts) | ||
5. [Testing](#testing) | ||
3. [Examples](#examples) | ||
4. [Setup](#setup) | ||
1. [Building test contracts](#building-test-contracts) | ||
2. [Testing](#testing) | ||
6. [Configuration](#config) | ||
6. [Simplified configuration](#simplified-configuration) | ||
7. [ConfigBuilder](#configbuilder) | ||
7. [Supported env vars](#supported-env-vars) | ||
8. [TOML configuration](#toml-configuration) | ||
1. [Simplified configuration](#simplified-configuration) | ||
2. [ClientBuilder](#clientbuilder) | ||
3. [Supported env vars](#supported-env-vars) | ||
4. [TOML configuration](#toml-configuration) | ||
9. [Automated gas price estimation](#automatic-gas-estimator) | ||
10. [DOT Graphs of transactions](#dot-graphs) | ||
11. [Using multiple private keys](#using-multiple-keys) | ||
12. [Experimental features](#experimental-features) | ||
13. [CLI](#cli) | ||
14. [Manual gas price estimation](#manual-gas-price-estimation) | ||
15. [Block Stats](#block-stats) | ||
15. [Single transaction tracing](#single-transaction-tracing) | ||
16. [Bulk transaction tracing](#bulk-transaction-tracing) | ||
13. [Gas bumping for slow transactions](#gas-bumping-for-slow-transactions) | ||
14. [CLI](#cli) | ||
1. [Manual gas price estimation](#manual-gas-price-estimation) | ||
2. [Block Stats](#block-stats) | ||
3. [Single transaction tracing](#single-transaction-tracing) | ||
4. [Bulk transaction tracing](#bulk-transaction-tracing) | ||
|
||
## Goals | ||
|
||
|
@@ -68,6 +69,7 @@ Reliable and debug-friendly Ethereum client | |
- [x] Block stats CLI | ||
- [x] Check if address has a pending nonce (transaction) and panic if it does | ||
- [x] DOT graph output for tracing | ||
- [x] Gas bumping for slow transactions | ||
|
||
You can read more about how ABI finding and contract map works [here](./docs/abi_finder_contract_map.md) and about contract store here [here](./docs/contract_store.md). | ||
|
||
|
@@ -193,11 +195,11 @@ This config uses what we consider reasonable defaults, such as: | |
* checking of RPC node health on client creation | ||
* no ephemeral keys | ||
|
||
### ConfigBuilder | ||
You can also use a `ConfigBuilder` to build a config programmatically. Here's an extensive example: | ||
### ClientBuilder | ||
You can also use a `ClientBuilder` to build a config programmatically. Here's an extensive example: | ||
|
||
```go | ||
cfg := builder. | ||
client, err := builder. | ||
// network | ||
WithNetworkName("my network"). | ||
WithRpcUrl("ws://localhost:8546"). | ||
|
@@ -217,10 +219,11 @@ cfg := builder. | |
// EIP-1559 and gas estimations | ||
WithEIP1559DynamicFees(true). | ||
WithDynamicGasPrices(120_000_000_000, 44_000_000_000). | ||
WithGasPriceEstimations(false, 10, seth.Priority_Fast). | ||
WithGasPriceEstimations(false, 10, seth.Priority_Fast). | ||
// gas bumping: retries, max gas price, bumping strategy function | ||
WithGasBumping(5, 100_000_000_000, PriorityBasedGasBumpingStrategyFn). | ||
Build() | ||
|
||
client, err := seth.NewClientWithConfig(cfg) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
@@ -548,6 +551,94 @@ Here's what they do: | |
- `slow_funds_return` will work only in `core` and when enabled it changes tx priority to `slow` and increases transaction timeout to 30 minutes. | ||
- `eip_1559_fee_equalizer` in case of EIP-1559 transactions if it detects that historical base fee and suggested/historical tip are more than 3 orders of magnitude apart, it will use the higher value for both (this helps in cases where base fee is almost 0 and transaction is never processed). | ||
|
||
## Gas bumping for slow transactions | ||
Seth has built-in gas bumping mechanism for slow transactions. If a transaction is not mined within a certain time frame (`Network`'s transaction timeout), Seth will automatically bump the gas price and resubmit the transaction. This feature is disabled by default and can be enabled by setting the `[gas_bumps] retries` to a non-zero number: | ||
```toml | ||
[gas_bumps] | ||
retries = 5 | ||
``` | ||
|
||
Once enabled, by default the amount, by which gas price is bumped depends on `gas_price_estimation_tx_priority` setting and is calculated as follows: | ||
- `Priority_Fast`: 30% increase | ||
- `Priority_Standard`: 15% increase | ||
- `Priority_Slow`: 5% increase | ||
- everything else: no increase | ||
|
||
You can cap max gas price by settings (in wei): | ||
```toml | ||
[gas_bumps] | ||
max_gas_price = 1000000000000 | ||
``` | ||
|
||
Once the gas price bump would go above the limit we stop bumping and use the last gas price that was below the limit. | ||
|
||
How gas price is calculated depends on transaction type: | ||
- for legacy transactions it's just the gas price | ||
- for EIP-1559 transactions it's the sum of gas fee cap and tip cap | ||
- for Blob transactions (EIP-4844) it's the sum of gas fee cap and tip cap and max fee per blob | ||
- for AccessList transactions (EIP-2930) it's just the gas price | ||
|
||
Please note that Blob and AccessList | ||
|
||
If you want to use a custom bumping strategy, you can use a function with [GasBumpStrategyFn](retry.go) type. Here's an example of a custom strategy that bumps the gas price by 100% for every retry: | ||
```go | ||
var customGasBumpStrategyFn = func(gasPrice *big.Int) *big.Int { | ||
return new(big.Int).Mul(gasPrice, big.NewInt(2)) | ||
} | ||
``` | ||
|
||
To use this strategy, you need to pass it to the `WithGasBumping` function in the `ClientBuilder`: | ||
```go | ||
var hundredGwei in64 = 100_000_000_000 | ||
client, err := builder. | ||
// other settings... | ||
WithGasBumping(5, hundredGwei, customGasBumpStrategyFn). | ||
Build() | ||
``` | ||
|
||
Or set it directly on Seth's config: | ||
```go | ||
// assuming sethClient is already created | ||
sethClient.Config.GasBumps.StrategyFn = customGasBumpStrategyFn | ||
``` | ||
|
||
Since strategy function only accepts a single parameter, if you want to base its behaviour on anything else than that you will need to capture these values from the context, in which you define the strategy function. For example, you can use a closure to capture the initial gas price: | ||
```go | ||
gasOracleClient := NewGasOracleClient() | ||
|
||
var oracleGasBumpStrategyFn = func(gasPrice *big.Int) *big.Int { | ||
// get the current gas price from the oracle | ||
suggestedGasPrice := gasOracleClient.GetCurrentGasPrice() | ||
|
||
// if oracle suggests a higher gas price, use it | ||
if suggestedGasPrice.Cmp(gasPrice) == 1 { | ||
return suggestedGasPrice | ||
} | ||
|
||
// otherwise bump by 100% | ||
return new(big.Int).Mul(gasPrice, big.NewInt(2)) | ||
} | ||
``` | ||
|
||
Currently, the gas bumping mechanism is available for: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's remove these lines, we've already described them before, or shorten it |
||
* Legacy transactions | ||
* EIP-1559 transactions. | ||
* Blob transactions (EIP-4844) | ||
* AccessList transactions (EIP-2930) | ||
|
||
Same strategy is applied to all types of transactions, regardless whether it's gas price, gas fee cap, gas tip cap or max blob fee. | ||
|
||
When enabled, gas bumping is used in two places: | ||
* during contract deployment via `DeployContract` function | ||
* inside `Decode()` function | ||
|
||
It is recommended to decrease transaction timeout when using gas bumping, as it will be effectively increased by the number of retries. So if you were running with 5 minutes timeout and 0 retries, you should set it to 1 minute and 5 retries | ||
or 30 seconds and 10 retries. | ||
|
||
Don't worry if while bumping logic executes previous transaction gets mined. In that case sending replacement transaction with higher gas will fail (because it is using the same nonce as original transaction) and we will retry waiting for the mining of the original transaction. | ||
|
||
**Gas bumping is only applied for submitted transaction. If transaction was rejected by the node (e.g. because of too low base fee) we will not bump the gas price nor try to submit it, because original transaction submission happens outside of Seth.** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sadly enough, that's true, haven't found any other possible workarounds?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup so inside
|
||
|
||
## CLI | ||
|
||
You can either define the network you want to interact with in your TOML config and then refer it in the CLI command, or you can pass all network parameters via env vars. Most of the examples below show how to use the former approach. | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we end the sentence? =)