Eviction policy

We look at two different rules to evict transactions that are in the transaction pool.

Fixed band

The rule is governed by a parameter mu >= 0.

Evict iff (1-mu) * basefee > fee_cap

  • For mu = 0, we evict as soon as basefee is above fee_cap.

  • If this is too strong, we can set mu = 0.1 to tolerate fee caps within a 10% lower band of basefee. For instance, if basefee = 10 and mu = 0.1, all transactions with fee cap greater than 9 are kept in the pool.

Trend-picker

We modify the rule above with a parameter increasing or decreasing the tolerance based on the current basefee trend.

Evict iff (1+delta) * (1-mu) * basefee > fee_cap

delta is computed from recent basefees. delta should be close to zero when basefee is stable, positive when basefee trends upwards and negative when basefee trends downwards. We suggest

delta = (basefee - moving_average(basefees, 10)) / basefee

where moving_average(basefees, 10) returns the average basefee over the last 10 blocks. We divide by basefee to normalise the rule (same behaviour at 1 Gwei basefee and at 100 Gwei basefee).

Stable basefee

We work out some numbers when basefee is overall stable, yet noisy. In the extreme case, a full block is mined, followed by an empty block, followed by a full block etc. In this case, basefee is either increased by 12.5% or decreased by 12.5%.

In [1]:
basefee = 10
basefees = [basefee]
for i in range(10):
    basefee = basefee * (1 + 0.125 * ((-1) ** i))
    basefees += [basefee]
print(basefees)
[10, 11.25, 9.84375, 11.07421875, 9.68994140625, 10.90118408203125, 9.538536071777344, 10.730853080749512, 9.389496445655823, 10.5631835013628, 9.24278556369245]
In [2]:
moving_averages = []
for i in range(5):
    moving_averages += [sum(basefees[i:(5+i)]) / 5]
moving_averages
Out[2]:
[10.37158203125,
 10.55181884765625,
 10.209526062011719,
 10.386946678161621,
 10.050002217292786]
In [3]:
deltas = [(basefees[i+6] - moving_averages[i])/basefees[i+6] for i in range(5)]
deltas
Out[3]:
[-0.08733478106116051,
 0.016684063396081538,
 -0.08733478106116051,
 0.016684063396081538,
 -0.08733478106116051]

We see that deltas are close to 0, albeit noisy. What is the tolerance of the policy?

In [4]:
mu = 0.1
band_sizes = [(1+d) * (1-mu) for d in deltas]
band_sizes
Out[4]:
[0.8213986970449555,
 0.9150156570564735,
 0.8213986970449555,
 0.9150156570564735,
 0.8213986970449555]

We end up keeping transactions with fee caps larger than ~91% of basefee.

Increasing basefee

In this case, full blocks are mined one after the other. Basefee increases by 12.5% each step.

In [5]:
basefee = 10
basefees = [basefee]
for i in range(10):
    basefee = basefee * (1 + 0.125)
    basefees += [basefee]
print(basefees)
[10, 11.25, 12.65625, 14.23828125, 16.01806640625, 18.02032470703125, 20.272865295410156, 22.806973457336426, 25.65784513950348, 28.865075781941414, 32.47321025468409]
In [6]:
moving_averages = []
for i in range(5):
    moving_averages += [sum(basefees[i:(5+i)]) / 5]
moving_averages
Out[6]:
[12.83251953125,
 14.43658447265625,
 16.24115753173828,
 18.271302223205566,
 20.555215001106262]
In [7]:
deltas = [(basefees[i+6] - moving_averages[i])/basefees[i+6] for i in range(5)]
deltas
Out[7]:
[0.3670100726138932,
 0.3670100726138932,
 0.3670100726138932,
 0.3670100726138932,
 0.3670100726138932]
In [8]:
mu = 0.1
band_sizes = [(1+d) * (1-mu) for d in deltas]
band_sizes
Out[8]:
[1.230309065352504,
 1.230309065352504,
 1.230309065352504,
 1.230309065352504,
 1.230309065352504]

This is the maximum value delta can achieve. With mu = 0.1, this implies evicting all transactions with fee cap smaller than 123% of the current basefee. In particular, we evict transactions that have fee cap greater than the current basefee, if their fee cap is smaller than 1.23 * basefee. This may be rationalised by the intuition that should basefee increase at this speed in a sustained manner, there are plenty more transactions with fee caps above 1.23 * basefee, so we are only evicting transactions that have posted smaller fee caps than these.

If we are unhappy with throwing away currently valid transactions (even if they are likely dominated by higer fee cap transactions), we can also use the eviction rule

Evict iff min((1+delta) * (1-mu), 1) * basefee > fee_cap