We look at two different rules to evict transactions that are in the transaction pool.
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.
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).
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%.
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]
moving_averages = []
for i in range(5):
moving_averages += [sum(basefees[i:(5+i)]) / 5]
moving_averages
[10.37158203125, 10.55181884765625, 10.209526062011719, 10.386946678161621, 10.050002217292786]
deltas = [(basefees[i+6] - moving_averages[i])/basefees[i+6] for i in range(5)]
deltas
[-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?
mu = 0.1
band_sizes = [(1+d) * (1-mu) for d in deltas]
band_sizes
[0.8213986970449555, 0.9150156570564735, 0.8213986970449555, 0.9150156570564735, 0.8213986970449555]
We end up keeping transactions with fee caps larger than ~91% of basefee.
In this case, full blocks are mined one after the other. Basefee increases by 12.5% each step.
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]
moving_averages = []
for i in range(5):
moving_averages += [sum(basefees[i:(5+i)]) / 5]
moving_averages
[12.83251953125, 14.43658447265625, 16.24115753173828, 18.271302223205566, 20.555215001106262]
deltas = [(basefees[i+6] - moving_averages[i])/basefees[i+6] for i in range(5)]
deltas
[0.3670100726138932, 0.3670100726138932, 0.3670100726138932, 0.3670100726138932, 0.3670100726138932]
mu = 0.1
band_sizes = [(1+d) * (1-mu) for d in deltas]
band_sizes
[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