Skip to content

Commit

Permalink
Update mempool check logic
Browse files Browse the repository at this point in the history
  • Loading branch information
dimriou committed Jul 17, 2024
1 parent 1d6e223 commit 7e447fd
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 18 deletions.
46 changes: 28 additions & 18 deletions core/chains/evm/gas/universal_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,20 @@ var (
)

const (
queryTimeout = 10 * time.Second
MinimumBumpPercentage = 10 // based on geth's spec
queryTimeout = 10 * time.Second

MinimumBumpPercentage = 10 // based on geth's spec
ConnectivityPercentile = 80
BaseFeeBufferPercentage = 40
)

type UniversalEstimatorConfig struct {
CacheTimeout time.Duration
BumpPercent uint16
CacheTimeout time.Duration

BlockHistoryRange uint64 // inclusive range
RewardPercentile float64
HasMempool bool
}

//go:generate mockery --quiet --name universalEstimatorClient --output ./mocks/ --case=underscore --structname UniversalEstimatorClient
Expand Down Expand Up @@ -331,21 +332,30 @@ func (u *UniversalEstimator) BumpDynamicFee(ctx context.Context, originalFee Dyn
bumpedMaxPriorityFeePerGas := originalFee.TipCap.AddPercentage(u.config.BumpPercent)
bumpedMaxFeePerGas := originalFee.FeeCap.AddPercentage(u.config.BumpPercent)

bumpedMaxPriorityFeePerGas, err = LimitBumpedFee(originalFee.TipCap, currentDynamicPrice.TipCap, bumpedMaxPriorityFeePerGas, maxPrice)
if err != nil {
return bumped, fmt.Errorf("maxPriorityFeePerGas error: %s", err.Error())
}
priorityFeeThreshold, err := u.getPriorityFeeThreshold()
if err != nil {
return
}
// If either of these two values are 0 it could be that the network has extremely low priority fees or most likely it doesn't have
// a mempool and priority fees are not taken into account. Either way, we should skip the connectivity check because we're only
// going to be charged for the base fee, which is mandatory.
if (priorityFeeThreshold.Cmp(assets.NewWeiI(0)) > 0) && (bumpedMaxPriorityFeePerGas.Cmp(assets.NewWeiI(0)) > 0) &&
bumpedMaxPriorityFeePerGas.Cmp(priorityFeeThreshold) > 0 {
return bumped, fmt.Errorf("bumpedMaxPriorityFeePergas: %s is above market's %sth percentile: %s, bumping is halted",
bumpedMaxPriorityFeePerGas, strconv.Itoa(ConnectivityPercentile), priorityFeeThreshold)
if u.config.HasMempool {
bumpedMaxPriorityFeePerGas, err = LimitBumpedFee(originalFee.TipCap, currentDynamicPrice.TipCap, bumpedMaxPriorityFeePerGas, maxPrice)
if err != nil {
return bumped, fmt.Errorf("maxPriorityFeePerGas error: %s", err.Error())
}

priorityFeeThreshold, e := u.getPriorityFeeThreshold()
if e != nil {
err = e
return
}

// If either of these two values are 0 it could be that the network has extremely low priority fees. We should skip the
// connectivity check because we're only going to be charged for the base fee, which is mandatory.
if (priorityFeeThreshold.Cmp(assets.NewWeiI(0)) > 0) && (bumpedMaxPriorityFeePerGas.Cmp(assets.NewWeiI(0)) > 0) &&
bumpedMaxPriorityFeePerGas.Cmp(priorityFeeThreshold) > 0 {
return bumped, fmt.Errorf("bumpedMaxPriorityFeePergas: %s is above market's %sth percentile: %s, bumping is halted",
bumpedMaxPriorityFeePerGas, strconv.Itoa(ConnectivityPercentile), priorityFeeThreshold)
}

} else {
// If the network doesn't have a mempool then transactions are processed in a FCFS manner and maxPriorityFeePerGas value is irrelevant.
// We just need to cap the value at maxPrice in case maxFeePerGas also gets capped.
bumpedMaxPriorityFeePerGas = assets.WeiMin(bumpedMaxPriorityFeePerGas, maxPrice)
}

bumpedMaxFeePerGas, err = LimitBumpedFee(originalFee.FeeCap, currentDynamicPrice.FeeCap, bumpedMaxFeePerGas, maxPrice)
Expand Down
35 changes: 35 additions & 0 deletions core/chains/evm/gas/universal_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ func TestUniversalEstimatorBumpDynamicFee(t *testing.T) {
cfg := gas.UniversalEstimatorConfig{
BlockHistoryRange: 2,
BumpPercent: 50,
HasMempool: true,
}

expectedFeeCap := originalFee.FeeCap.AddPercentage(cfg.BumpPercent)
Expand Down Expand Up @@ -401,6 +402,7 @@ func TestUniversalEstimatorBumpDynamicFee(t *testing.T) {
cfg := gas.UniversalEstimatorConfig{
BlockHistoryRange: 1,
BumpPercent: 50,
HasMempool: true,
}

u := gas.NewUniversalEstimator(logger.Test(t), client, cfg, chainID, nil)
Expand Down Expand Up @@ -431,6 +433,7 @@ func TestUniversalEstimatorBumpDynamicFee(t *testing.T) {
cfg := gas.UniversalEstimatorConfig{
BlockHistoryRange: 1,
BumpPercent: 50,
HasMempool: true,
}

u := gas.NewUniversalEstimator(logger.Test(t), client, cfg, chainID, nil)
Expand Down Expand Up @@ -460,6 +463,7 @@ func TestUniversalEstimatorBumpDynamicFee(t *testing.T) {
cfg := gas.UniversalEstimatorConfig{
BlockHistoryRange: 1,
BumpPercent: 50,
HasMempool: true,
}

u := gas.NewUniversalEstimator(logger.Test(t), client, cfg, chainID, nil)
Expand Down Expand Up @@ -497,4 +501,35 @@ func TestUniversalEstimatorBumpDynamicFee(t *testing.T) {
_, err := u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil)
assert.Error(t, err)
})

t.Run("ignores maxPriorityFeePerGas if there is no mempool", func(t *testing.T) {
client := mocks.NewUniversalEstimatorClient(t)
originalFee := gas.DynamicFee{
FeeCap: assets.NewWeiI(40),
TipCap: assets.NewWeiI(0),
}

// Market fees
baseFee := big.NewInt(10)
maxPriorityFeePerGas := big.NewInt(0)
feeHistoryResult := &ethereum.FeeHistory{
OldestBlock: big.NewInt(1),
Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(0)}}, // first one represents market price and second one connectivity price
BaseFee: []*big.Int{baseFee},
GasUsedRatio: nil,
}
client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once()

cfg := gas.UniversalEstimatorConfig{
BlockHistoryRange: 1,
BumpPercent: 20,
HasMempool: false,
}

u := gas.NewUniversalEstimator(logger.Test(t), client, cfg, chainID, nil)
bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil)
assert.NoError(t, err)
assert.Equal(t, assets.NewWeiI(0), (*assets.Wei)(maxPriorityFeePerGas))
assert.Equal(t, originalFee.FeeCap.AddPercentage(20), bumpedFee.FeeCap)
})
}

0 comments on commit 7e447fd

Please sign in to comment.