Skip to content

Conversation

dlipicar
Copy link
Collaborator

@dlipicar dlipicar commented Jul 21, 2025

Introduce module to estimate/suggest:

  • base + priority gas prices
  • maxPriorityFeePerGas, maxFeePerGas
  • network congestion
  • number of blocks/time for inclusion of a tx in the chain
  • gas used for a given tx

Comparison output:

➜  gas-comparison git:(feat/gas-estimator) go run . -infura-api-key=$STATUS_BUILD_INFURA_TOKEN
🔥 Multi-Network Gas Fee Comparison Tool
Comparing our current implementation, old implementation, and Infura's Gas API across multiple networks
================================================================================

🔷 Ethereum Mainnet (1)
------------------------------------------------------------
📊 Fetching our gas suggestions for Ethereum Mainnet...
📊 Fetching old estimator suggestions for Ethereum Mainnet...
📊 Fetching Infura's gas suggestions for Ethereum Mainnet...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                        1840413472 wei
   Gas Tip Cap:                          480198 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:           1849010124 wei
   Old Implementation:               1895235377 wei
   Current vs Old:                    -46225253 wei (-2.4%)
   Infura:                           1839933274 wei
   Current vs Infura:                   9076850 wei (+0.5%)

🔸 LOW PRIORITY FEES
   Current Implementation:              7253674 wei
   Old Implementation:                  7253674 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                              7253674 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:            561320079 wei
   Old Implementation:                561320079 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                           2000000000 wei
   Current vs Infura:               -1438679921 wei (-71.9%)

🔸 HIGH PRIORITY FEES
   Current Implementation:           2000000000 wei
   Old Implementation:               2000000000 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                           2000000000 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW MAX FEES
   Current Implementation:           1902489051 wei
   Old Implementation:               1902489051 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                           1847186948 wei
   Current vs Infura:                  55302103 wei (+3.0%)

🔸 MEDIUM MAX FEES
   Current Implementation:           4010989917 wei
   Old Implementation:               3432350137 wei
   Current vs Old:                    578639780 wei (+16.9%)
   Infura:                           4631104582 wei
   Current vs Infura:                -620114665 wei (-13.4%)

🔸 HIGH MAX FEES
   Current Implementation:           7344905215 wei
   Old Implementation:               6766265435 wei
   Current vs Old:                    578639780 wei (+8.6%)
   Infura:                           4631104582 wei
   Current vs Infura:                2713800633 wei (+58.6%)

🔸 LOW WAIT TIME
   Wait Time (Current):    72.0-84.0 seconds
   Wait Time (Old):        125 seconds
   Wait Time (Infura):     12.0-48.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    12.0-24.0 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     12.0-36.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    12.0-24.0 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     12.0-24.0 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.082
   Infura:                 0.888
   Difference:             -0.806



🔵 Arbitrum One (42161)
------------------------------------------------------------
📊 Fetching our gas suggestions for Arbitrum One...
📊 Fetching old estimator suggestions for Arbitrum One...
📊 Fetching Infura's gas suggestions for Arbitrum One...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                          10000000 wei
   Gas Tip Cap:                               0 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:             10000000 wei
   Old Implementation:                 10249999 wei
   Current vs Old:                      -249999 wei (-2.4%)
   Infura:                             10000000 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                                    0 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                                    0 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 HIGH PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                                    0 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW MAX FEES
   Current Implementation:             10250000 wei
   Old Implementation:                 10249999 wei
   Current vs Old:                            1 wei (+0.0%)
   Infura:                             10000000 wei
   Current vs Infura:                    250000 wei (+2.5%)

🔸 MEDIUM MAX FEES
   Current Implementation:             41000000 wei
   Old Implementation:                 40999996 wei
   Current vs Old:                            4 wei (+0.0%)
   Infura:                             13500000 wei
   Current vs Infura:                  27500000 wei (+203.7%)

🔸 HIGH MAX FEES
   Current Implementation:            102500000 wei
   Old Implementation:                102499990 wei
   Current vs Old:                           10 wei (+0.0%)
   Infura:                             17000000 wei
   Current vs Infura:                  85500000 wei (+502.9%)

🔸 LOW WAIT TIME
   Wait Time (Current):    0.2-0.5 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     0.2-1.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    0.2-0.5 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     0.2-0.8 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    0.2-0.5 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     0.2-0.5 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000
   Infura:                 0.000
   Difference:             +0.000



🔴 Optimism (10)
------------------------------------------------------------
📊 Fetching our gas suggestions for Optimism...
📊 Fetching old estimator suggestions for Optimism...
📊 Fetching Infura's gas suggestions for Optimism...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                           1000413 wei
   Gas Tip Cap:                         1000000 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:                  412 wei
   Old Implementation:                      422 wei
   Current vs Old:                          -10 wei (-2.4%)
   Infura:                                  412 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:                 2005 wei
   Old Implementation:                     2005 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               100000 wei
   Current vs Infura:                    -97995 wei (-98.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:               772554 wei
   Old Implementation:                   772554 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               100000 wei
   Current vs Infura:                    672554 wei (+672.6%)

🔸 HIGH PRIORITY FEES
   Current Implementation:              1421824 wei
   Old Implementation:                  1421824 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               100000 wei
   Current vs Infura:                   1321824 wei (+1321.8%)

🔸 LOW MAX FEES
   Current Implementation:                 2427 wei
   Old Implementation:                     2427 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               100824 wei
   Current vs Infura:                    -98397 wei (-97.6%)

🔸 MEDIUM MAX FEES
   Current Implementation:               774242 wei
   Old Implementation:                   774242 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               101236 wei
   Current vs Infura:                    673006 wei (+664.8%)

🔸 HIGH MAX FEES
   Current Implementation:              1426044 wei
   Old Implementation:                  1426044 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                               104120 wei
   Current vs Infura:                   1321924 wei (+1269.6%)

🔸 LOW WAIT TIME
   Wait Time (Current):    12.0-14.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-8.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-6.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-4.0 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000
   Infura:                 0.060
   Difference:             -0.060



🔵 Base (8453)
------------------------------------------------------------
📊 Fetching our gas suggestions for Base...
📊 Fetching old estimator suggestions for Base...
📊 Fetching Infura's gas suggestions for Base...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                           4806078 wei
   Gas Tip Cap:                         1000000 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:              3876688 wei
   Old Implementation:                  3973605 wei
   Current vs Old:                       -96917 wei (-2.4%)
   Infura:                              3806078 wei
   Current vs Infura:                     70610 wei (+1.9%)

🔸 LOW PRIORITY FEES
   Current Implementation:                90308 wei
   Old Implementation:                    90308 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                              1159529 wei
   Current vs Infura:                  -1069221 wei (-92.2%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:              1000000 wei
   Old Implementation:                  1000000 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                              8000000 wei
   Current vs Infura:                  -7000000 wei (-87.5%)

🔸 HIGH PRIORITY FEES
   Current Implementation:             10000000 wei
   Old Implementation:                 10000000 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                              8001805 wei
   Current vs Infura:                   1998195 wei (+25.0%)

🔸 LOW MAX FEES
   Current Implementation:              4063913 wei
   Old Implementation:                  4063913 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                              8771685 wei
   Current vs Infura:                  -4707772 wei (-53.7%)

🔸 MEDIUM MAX FEES
   Current Implementation:             16894420 wei
   Old Implementation:                 16894420 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                             23224312 wei
   Current vs Infura:                  -6329892 wei (-27.3%)

🔸 HIGH MAX FEES
   Current Implementation:             49736050 wei
   Old Implementation:                 49736050 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                             46062585 wei
   Current vs Infura:                   3673465 wei (+8.0%)

🔸 LOW WAIT TIME
   Wait Time (Current):    12.0-14.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-8.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-6.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds
   Wait Time (Infura):     2.0-4.0 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000
   Infura:                 1.020
   Difference:             -1.020



🟣 Polygon (137)
------------------------------------------------------------
📊 Fetching our gas suggestions for Polygon...
📊 Fetching old estimator suggestions for Polygon...
📊 Fetching Infura's gas suggestions for Polygon...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                       27000000096 wei
   Gas Tip Cap:                     27000000000 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:                   96 wei
   Old Implementation:                       98 wei
   Current vs Old:                           -2 wei (-2.0%)
   Infura:                                   96 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:          27000000093 wei
   Old Implementation:              27000000093 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                          30000000000 wei
   Current vs Infura:               -2999999907 wei (-10.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:          30066666666 wei
   Old Implementation:              30129639444 wei
   Current vs Old:                    -62972778 wei (-0.2%)
   Infura:                          30000000000 wei
   Current vs Infura:                  66666666 wei (+0.2%)

🔸 HIGH PRIORITY FEES
   Current Implementation:          49999999906 wei
   Old Implementation:              49999999906 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                          30000000000 wei
   Current vs Infura:               19999999906 wei (+66.7%)

🔸 LOW MAX FEES
   Current Implementation:          27000000191 wei
   Old Implementation:              27000000191 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                          30000000096 wei
   Current vs Infura:               -2999999905 wei (-10.0%)

🔸 MEDIUM MAX FEES
   Current Implementation:          30066666813 wei
   Old Implementation:              30129639836 wei
   Current vs Old:                    -62973023 wei (-0.2%)
   Infura:                          30000000130 wei
   Current vs Infura:                  66666683 wei (+0.2%)

🔸 HIGH MAX FEES
   Current Implementation:          50000000151 wei
   Old Implementation:              50000000886 wei
   Current vs Old:                         -735 wei (-0.0%)
   Infura:                          30000000164 wei
   Current vs Infura:               19999999987 wei (+66.7%)

🔸 LOW WAIT TIME
   Wait Time (Current):    13.5-15.8 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-8.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    2.2-4.5 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-6.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    2.2-4.5 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-4.0 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.050
   Infura:                 0.032
   Difference:             +0.018



⚪ BNB Smart Chain (56)
------------------------------------------------------------
📊 Fetching our gas suggestions for BNB Smart Chain...
📊 Fetching old estimator suggestions for BNB Smart Chain...
err: EIP-1559 is not supported on this chain
📊 Fetching Infura's gas suggestions for BNB Smart Chain...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                         100000000 wei
   Gas Tip Cap:                       100000000 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:                    0 wei
   Infura:                                    0 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:            100000000 wei
   Infura:                            100000000 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:            100000001 wei
   Infura:                            100000000 wei
   Current vs Infura:                         1 wei (+0.0%)

🔸 HIGH PRIORITY FEES
   Current Implementation:            202000000 wei
   Infura:                            100000000 wei
   Current vs Infura:                 102000000 wei (+102.0%)

🔸 LOW MAX FEES
   Current Implementation:            100000000 wei
   Infura:                            100000000 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 MEDIUM MAX FEES
   Current Implementation:            100000001 wei
   Infura:                            100000000 wei
   Current vs Infura:                         1 wei (+0.0%)

🔸 HIGH MAX FEES
   Current Implementation:            202000000 wei
   Infura:                            100000000 wei
   Current vs Infura:                 102000000 wei (+102.0%)

🔸 LOW WAIT TIME
   Wait Time (Current):    1.5-2.2 seconds
   Wait Time (Infura):     0.7-2.7 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    0.8-1.5 seconds
   Wait Time (Infura):     0.7-2.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    0.8-1.5 seconds
   Wait Time (Infura):     0.7-1.3 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000
   Infura:                 0.000
   Difference:             +0.000



⚪ Linea (59144)
------------------------------------------------------------
📊 Fetching our gas suggestions for Linea...
📊 Fetching old estimator suggestions for Linea...
📊 Fetching Infura's gas suggestions for Linea...
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                          53809000 wei
   Gas Tip Cap:                        47870937 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:                    7 wei
   Old Implementation:                        7 wei
   Current vs Old:                            0 wei (+0.0%)
   Infura:                                    7 wei
   Current vs Infura:                         0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:             54017142 wei
   Old Implementation:                 53808993 wei
   Current vs Old:                       208149 wei (+0.4%)
   Infura:                             53808993 wei
   Current vs Infura:                    208149 wei (+0.4%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:             54017142 wei
   Old Implementation:                 53808993 wei
   Current vs Old:                       208149 wei (+0.4%)
   Infura:                             53808993 wei
   Current vs Infura:                    208149 wei (+0.4%)

🔸 HIGH PRIORITY FEES
   Current Implementation:             54017142 wei
   Old Implementation:                 53808993 wei
   Current vs Old:                       208149 wei (+0.4%)
   Infura:                             53808993 wei
   Current vs Infura:                    208149 wei (+0.4%)

🔸 LOW MAX FEES
   Current Implementation:             54017156 wei
   Old Implementation:                 53809000 wei
   Current vs Old:                       208156 wei (+0.4%)
   Infura:                             53809000 wei
   Current vs Infura:                    208156 wei (+0.4%)

🔸 MEDIUM MAX FEES
   Current Implementation:             54017156 wei
   Old Implementation:                 53809021 wei
   Current vs Old:                       208135 wei (+0.4%)
   Infura:                             53809003 wei
   Current vs Infura:                    208153 wei (+0.4%)

🔸 HIGH MAX FEES
   Current Implementation:             54017156 wei
   Old Implementation:                 53809063 wei
   Current vs Old:                       208093 wei (+0.4%)
   Infura:                             53809005 wei
   Current vs Infura:                    208151 wei (+0.4%)

🔸 LOW WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-8.0 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-6.0 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        15 seconds
   Wait Time (Infura):     2.0-4.0 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000
   Infura:                 0.000
   Difference:             +0.000



⚪ Status Network Sepolia (1660990954)
------------------------------------------------------------
📊 Fetching our gas suggestions for Status Network Sepolia...
📊 Fetching old estimator suggestions for Status Network Sepolia...
📊 Fetching Infura's gas suggestions for Status Network Sepolia...
⚠️  Infura API not available for Status Network Sepolia: API returned status 400: {"statusCode":400,"message":"'1660990954' is not a supported chain id."}
📊 Showing our implementation vs old implementation:

📋 COMPARISON RESULTS
============================================================

📋 NODE SUGGESTIONS
═══════════════════════════════════════════════════════════════════════════
   Gas Price:                                 0 wei
   Gas Tip Cap:                               3 wei
═══════════════════════════════════════════════════════════════════════════

🔸 BASE FEE
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 LOW PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 MEDIUM PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 HIGH PRIORITY FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 LOW MAX FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 MEDIUM MAX FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 HIGH MAX FEES
   Current Implementation:                    0 wei
   Old Implementation:                        0 wei
   Current vs Old:                            0 wei (+0.0%)

🔸 LOW WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds

🔸 MEDIUM WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds

🔸 HIGH WAIT TIME
   Wait Time (Current):    2.0-4.0 seconds
   Wait Time (Old):        5 seconds

🔸 NETWORK CONGESTION
   Current Implementation: 0.000


================================================================================
✅ Multi-network comparison complete!

@dlipicar dlipicar force-pushed the feat/gas-estimator branch from c7344bc to e44b74d Compare July 21, 2025 22:38
@dlipicar dlipicar force-pushed the feat/ethclient branch 3 times, most recently from a7ee8ac to c21c8e6 Compare July 22, 2025 12:35
@dlipicar dlipicar force-pushed the feat/gas-estimator branch 2 times, most recently from 21280d6 to b6cfb2b Compare July 22, 2025 16:57
@dlipicar dlipicar force-pushed the feat/gas-estimator branch from b6cfb2b to 7493005 Compare August 4, 2025 17:15
@dlipicar dlipicar changed the base branch from feat/ethclient to master August 4, 2025 17:16
@dlipicar dlipicar force-pushed the feat/gas-estimator branch 2 times, most recently from b7beaea to d9d02d6 Compare August 12, 2025 19:43
@dlipicar dlipicar marked this pull request as ready for review August 12, 2025 19:44
@codecov-commenter
Copy link

codecov-commenter commented Aug 12, 2025

Codecov Report

❌ Patch coverage is 84.59119% with 98 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.98%. Comparing base (dfd87e0) to head (3a53827).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
pkg/gas/mock/ethclient.go 0.00% 33 Missing ⚠️
pkg/gas/gasprice_linea.go 46.42% 15 Missing ⚠️
pkg/gas/infura/client.go 78.57% 6 Missing and 3 partials ⚠️
pkg/gas/suggestions_linea.go 85.48% 6 Missing and 3 partials ⚠️
pkg/balance/fetcher/mock/fetcher.go 75.00% 8 Missing ⚠️
pkg/gas/suggestions_l2.go 87.75% 4 Missing and 2 partials ⚠️
pkg/gas/congestion.go 85.71% 2 Missing and 1 partial ⚠️
pkg/gas/inclusion.go 93.02% 3 Missing ⚠️
pkg/gas/priorityfee.go 88.00% 2 Missing and 1 partial ⚠️
pkg/gas/suggestions_l1.go 95.08% 2 Missing and 1 partial ⚠️
... and 2 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master       #7       +/-   ##
===========================================
- Coverage   87.28%   42.98%   -44.31%     
===========================================
  Files           5       32       +27     
  Lines         236     1724     +1488     
===========================================
+ Hits          206      741      +535     
- Misses         26      966      +940     
- Partials        4       17       +13     
Files with missing lines Coverage Δ
pkg/ethclient/mock/client.go 100.00% <100.00%> (ø)
pkg/ethclient/types.go 0.00% <ø> (ø)
pkg/gas/gasprice.go 100.00% <100.00%> (ø)
pkg/gas/infura/types.go 100.00% <100.00%> (ø)
pkg/gas/suggestions.go 100.00% <100.00%> (ø)
pkg/gas/suggestions_common.go 100.00% <100.00%> (ø)
pkg/gas/txgas_linea.go 100.00% <100.00%> (ø)
pkg/gas/congestion.go 85.71% <85.71%> (ø)
pkg/gas/inclusion.go 93.02% <93.02%> (ø)
pkg/gas/priorityfee.go 88.00% <88.00%> (ø)
... and 9 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dlipicar dlipicar force-pushed the feat/gas-estimator branch from 31c05bf to 3a53827 Compare August 12, 2025 21:53
@dlipicar dlipicar changed the title feat_: gas estimator feat: gas estimator Aug 12, 2025

// GetGasSuggestions retrieves gas fee suggestions from Infura's Gas API
func (c *Client) GetGasSuggestions(ctx context.Context, networkID int) (*GasResponse, error) {
url := fmt.Sprintf("%s/networks/%d/suggestedGasFees", c.baseURL, networkID)
Copy link

Choose a reason for hiding this comment

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

We can move this pattern string as const on top of the file for more convenient editing later.
Also baseURL used 2 times above could be a const on top.

wdyt?

gasPrice := suggestGasPrice(feeHistory, config.GasPriceEstimationBlocks)

// Apply multiplier to BaseFee
suggestedBaseFee := new(big.Int).Mul(gasPrice.BaseFeePerGas, big.NewInt(int64(config.BaseFeeMultiplier*1000)))
Copy link

Choose a reason for hiding this comment

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

Question: do we use multiplying and dividing to avoid using big.Float?

return big.NewInt(0)
}

index := (len(sortedData) * int(math.Ceil(percentile))) / 100
Copy link

@vkjr vkjr Aug 14, 2025

Choose a reason for hiding this comment

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

It seems that this implementation tends to return bigger indexes. And the check index >= len fixes only the last case.

If we will be looking for 10th percentile in array [10,20,30,40,50,60,70,80,90,100], it will return index 1, which will result in value 20.

Example testcase that I've used:

func TestGetPercentile_TenValues(t *testing.T) {
	// Test with 10 values evenly distributed from 10 to 100
	data := []*big.Int{
		big.NewInt(10), big.NewInt(20), big.NewInt(30), big.NewInt(40), big.NewInt(50),
		big.NewInt(60), big.NewInt(70), big.NewInt(80), big.NewInt(90), big.NewInt(100),
	}

	assert.Equal(t, big.NewInt(10), getPercentile(data, 10))
	assert.Equal(t, big.NewInt(30), getPercentile(data, 25))
	assert.Equal(t, big.NewInt(50), getPercentile(data, 50))	
	assert.Equal(t, big.NewInt(80), getPercentile(data, 75))
	assert.Equal(t, big.NewInt(90), getPercentile(data, 90))
	assert.Equal(t, big.NewInt(100), getPercentile(data, 95))
	assert.Equal(t, big.NewInt(100), getPercentile(data, 99))
	assert.Equal(t, big.NewInt(100), getPercentile(data, 100))
	
	// Edge cases
	assert.Equal(t, big.NewInt(10), getPercentile(data, 0))   // 0th percentile = minimum
	assert.Equal(t, big.NewInt(10), getPercentile(data, 5))   // 5th percentile
}

As an alternative, here is a function with "nearest-rank" percentile methods and few more checks:

// getPercentile calculates the value at a given percentile from sorted data
// Uses the "nearest-rank" method: index = ceil(percentile/100 * n) - 1
func getPercentile(sortedData []*big.Int, percentile float64) *big.Int {
	if len(sortedData) == 0 {
		return big.NewInt(0)
	}

	n := len(sortedData)

	// Handle edge cases
	if percentile <= 0 {
		return new(big.Int).Set(sortedData[0])
	}
	if percentile >= 100 {
		return new(big.Int).Set(sortedData[n-1])
	}

	// Calculate the rank using nearest-rank method
	rank := math.Ceil(percentile / 100.0 * float64(n))

	// Convert to 0-based index
	index := int(rank) - 1

	// Ensure index is within bounds (should already be, but safety check)
	if index < 0 {
		index = 0
	}
	if index >= n {
		index = n - 1
	}

	return new(big.Int).Set(sortedData[index])
}

)

func suggestGasPrice(feeHistory *ethclient.FeeHistory, nBlocks int) *GasPrice {
estimatedBaseFee := feeHistory.BaseFeePerGas[len(feeHistory.BaseFeePerGas)-1]
Copy link

Choose a reason for hiding this comment

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

Possible panic if len is 0

Copy link

Choose a reason for hiding this comment

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

if feeHistory is empty for some reason we might want to return fallback prices


// Use congestion-based logic
networkCongestion := calculateNetworkCongestionFromHistory(feeHistory, config.NetworkCongestionBlocks)
congestionFactor := new(big.Float).SetFloat64(10 * networkCongestion)
Copy link

@vkjr vkjr Aug 14, 2025

Choose a reason for hiding this comment

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

There are some magic numbers here and there. Wdyt about extracting them as constants or even moving to separate file?

  // priorityfee.go:32
  return big.NewInt(1000000000) // 1 gwei fallback

  // suggestions_test.go:26  
  return 21000, nil // Default gas limit for simple transfers

  // suggestions_l1.go:48
  highBaseFee := new(big.Int).Mul(suggestedBaseFee, big.NewInt(2))

  // suggestions_l2.go:37
  highBaseFee := new(big.Int).Mul(suggestedBaseFee, big.NewInt(10))

  2. Precision-related magic numbers:
  // suggestions_l1.go:32-33
  suggestedBaseFee := new(big.Int).Mul(gasPrice.BaseFeePerGas, big.NewInt(int64(config.BaseFeeMultiplier*1000)))
  suggestedBaseFee.Div(suggestedBaseFee, big.NewInt(1000))

  3. Congestion multiplier:
  // suggestions_l1.go:37
  congestionFactor := new(big.Float).SetFloat64(10 * networkCongestion)

Suggestion:

  const (
    // Gas estimation constants
    DefaultGasLimit         = 21000        // Standard ETH transfer gas limit
    DefaultBaseFeeMultiplier = 1.025       // 2.5% buffer for base fee volatility

    // Fee calculation precision
    BaseFeeMultiplierPrecision = 1000      // For fixed-point arithmetic

    // Priority fee multipliers
    L1HighBaseFeeMultiplier = 2            // 2x base fee for L1 high priority
    L2HighBaseFeeMultiplier = 10           // 10x base fee for L2 high priority
    CongestionMultiplier    = 10           // Congestion adjustment factor

    // Fallback values (in wei)
    FallbackPriorityFeeWei = 1000000000    // 1 gwei
)

Comment on lines +41 to +42

medianIndex := len(sortedFees) / 2
Copy link

Choose a reason for hiding this comment

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

For an even number of elements, it will return the second middle element instead of the average. Suggestion:

Suggested change
medianIndex := len(sortedFees) / 2
n := len(sortedFees)
if n%2 == 1 {
// Odd: [1,3,5] gwei -> median = 3 gwei
return new(big.Int).Set(sortedFees[n/2])
}
// Even: [1,2,4,5] gwei -> median = (2+4)/2 = 3 gwei
median := new(big.Int).Add(sortedFees[n/2-1], sortedFees[n/2])
return median.Div(median, big.NewInt(2))

Choose a reason for hiding this comment

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

You're right, that's how the median value should be calculated, but for our current purpose, it doesn't matter too much.

func getL1Suggestions(ctx context.Context, ethClient EthClient, config SuggestionsConfig, callMsg *ethereum.CallMsg) (*TxSuggestions, error) {
ret := &TxSuggestions{}

gasLimit, err := estimateTxGas(ctx, ethClient, callMsg)
Copy link

Choose a reason for hiding this comment

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

Do we need an additional estimateTxGas function here (and in suggestions_l2.go)?
A few lines below, you call ethClient.FeeHistory directly.

For uniformity, perhaps you could call ethClient.EstimateGas here?

}

func calculatePriorityFee(priorityFees []*big.Int) *big.Int {
if len(priorityFees) == 0 {
Copy link

Choose a reason for hiding this comment

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

I think this fallback value could be defined in SuggestionsConfig and come here as the second parameter, defaultFee.

@@ -0,0 +1,46 @@
package gas
Copy link

Choose a reason for hiding this comment

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

Minor. But maybe it's worth optimizing 90% mem allocations

Suggested change
package gas
func suggestGasPrice2(feeHistory *ethclient.FeeHistory, nBlocks int, fallbackFee *big.Int) *GasPrice {
if len(feeHistory.BaseFeePerGas) == 0 {
return &GasPrice{
BaseFeePerGas: new(big.Int).Set(fallbackFee),
LowPriorityFeePerGas: new(big.Int).Set(fallbackFee),
MediumPriorityFeePerGas: new(big.Int).Set(fallbackFee),
HighPriorityFeePerGas: new(big.Int).Set(fallbackFee),
}
}
estimatedBaseFee := feeHistory.BaseFeePerGas[len(feeHistory.BaseFeePerGas)-1]
ret := &GasPrice{
BaseFeePerGas: estimatedBaseFee,
LowPriorityFeePerGas: calculatePriorityFeeFromHistory2(feeHistory, nBlocks, LowPriorityFeeIndex, fallbackFee),
MediumPriorityFeePerGas: calculatePriorityFeeFromHistory2(feeHistory, nBlocks, MediumPriorityFeeIndex, fallbackFee),
HighPriorityFeePerGas: calculatePriorityFeeFromHistory2(feeHistory, nBlocks, HighPriorityFeeIndex, fallbackFee),
}
return ret
}
// calculatePriorityFeeFromHistory2 calculates priority fee directly from fee history without creating intermediate slices
func calculatePriorityFeeFromHistory2(feeHistory *ethclient.FeeHistory, nBlocks int, rewardsPercentileIndex int, fallbackFee *big.Int) *big.Int {
if len(feeHistory.Reward) == 0 {
return new(big.Int).Set(fallbackFee)
}
validFees := make([]*big.Int, 0, min(len(feeHistory.Reward), nBlocks))
// Start from the end and work backwards, taking only nBlocks
startIdx := max(len(feeHistory.Reward)-nBlocks, 0)
for i := startIdx; i < len(feeHistory.Reward); i++ {
blockRewards := feeHistory.Reward[i]
if rewardsPercentileIndex < len(blockRewards) && blockRewards[rewardsPercentileIndex] != nil {
validFees = append(validFees, new(big.Int).Set(blockRewards[rewardsPercentileIndex]))
}
}
return calculatePriorityFee2(validFees, fallbackFee)
}
func calculatePriorityFee2(fees []*big.Int, fallbackFee *big.Int) *big.Int {
if len(fees) == 0 {
return new(big.Int).Set(fallbackFee) // fallback
}
// Sort in place
slices.SortFunc(fees, func(a, b *big.Int) int {
return a.Cmp(b)
})
n := len(fees)
if n%2 == 1 {
return new(big.Int).Set(fees[n/2]) // Odd: middle element
}
// Even: average
mid1, mid2 := fees[n/2-1], fees[n/2]
median := new(big.Int).Add(mid1, mid2)
return median.Div(median, big.NewInt(2))
}

Copy link

@friofry friofry left a comment

Choose a reason for hiding this comment

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

Looks good to me!
It's easy to review small files. The examples work well.

Added a few suggestions

@@ -420,6 +420,15 @@ type withdrawalJSON struct {
Amount *hexutil.Big `json:"amount"`
}

// Transaction types.
const (
LegacyTxType = 0x00

Choose a reason for hiding this comment

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

We certainly depend on go-ethereum, why don't we use these constants directly from go-etherem's types package?

Comment on lines +41 to +42

medianIndex := len(sortedFees) / 2

Choose a reason for hiding this comment

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

You're right, that's how the median value should be calculated, but for our current purpose, it doesn't matter too much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants