Skip to content

Commit 66adebe

Browse files
committed
Test and fix miner tip calculation for EIP-1559
1 parent f576d41 commit 66adebe

File tree

4 files changed

+85
-11
lines changed

4 files changed

+85
-11
lines changed

eth/abc.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,6 +2686,18 @@ def get_gas_price(self, transaction: SignedTransactionAPI) -> int:
26862686
"""
26872687
...
26882688

2689+
@abstractmethod
2690+
def get_tip(self, transaction: SignedTransactionAPI) -> int:
2691+
"""
2692+
Return the gas price that gets allocated to the miner/validator.
2693+
2694+
Pre-EIP-1559 that would be the full transaction gas price. After, it
2695+
would be the tip price (potentially reduced, if the base fee is so high
2696+
that it surpasses the transaction's maximum gas price after adding the
2697+
tip).
2698+
"""
2699+
...
2700+
26892701
#
26902702
# Access to account db
26912703
#

eth/vm/forks/london/state.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ def finalize_computation(
119119
self.vm_state.delta_balance(computation.msg.sender, gas_refund_amount)
120120

121121
# Miner Fees
122-
transaction_fee = \
123-
(transaction.gas - gas_remaining - gas_refund) * transaction.max_priority_fee_per_gas
122+
gas_used = transaction.gas - gas_remaining - gas_refund
123+
transaction_fee = gas_used * self.vm_state.get_tip(transaction)
124124
self.vm_state.logger.debug2(
125125
'TRANSACTION FEE: %s -> %s',
126126
transaction_fee,

eth/vm/state.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,27 @@ def difficulty(self) -> int:
8888
def gas_limit(self) -> int:
8989
return self.execution_context.gas_limit
9090

91-
def get_gas_price(self, transaction: SignedTransactionAPI) -> int:
91+
def _get_burn_price(self) -> int:
92+
"""
93+
How much of the gas price will be burned?
94+
"""
9295
execution_context = self.execution_context
9396
try:
94-
base_gas_price = execution_context.base_fee_per_gas
97+
return execution_context.base_fee_per_gas
9598
except AttributeError:
96-
return transaction.gas_price
97-
else:
98-
effective_price = min(
99-
transaction.max_fee_per_gas,
100-
transaction.max_priority_fee_per_gas + base_gas_price,
101-
)
102-
return effective_price
99+
return 0
100+
101+
def get_tip(self, transaction: SignedTransactionAPI) -> int:
102+
return min(
103+
transaction.max_fee_per_gas - self._get_burn_price(),
104+
transaction.max_priority_fee_per_gas,
105+
)
106+
107+
def get_gas_price(self, transaction: SignedTransactionAPI) -> int:
108+
return min(
109+
transaction.max_fee_per_gas,
110+
transaction.max_priority_fee_per_gas + self._get_burn_price(),
111+
)
103112

104113
#
105114
# Access to account db

tests/core/vm/test_rewards.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
tangerine_whistle_at,
2222
constantinople_at,
2323
petersburg_at,
24+
berlin_at,
25+
london_at,
2426
genesis,
2527
)
28+
from eth.tools.factories.transaction import new_fee_burn_transaction
2629

2730

2831
@pytest.mark.parametrize(
@@ -311,3 +314,53 @@ def test_rewards_nephew_uncle_different_vm(
311314
# But we also ensure the balance matches the numbers that we calculated on paper
312315
assert coinbase_balance == to_wei(miner_1_balance, 'ether')
313316
assert other_miner_balance == to_wei(miner_2_balance, 'ether')
317+
318+
319+
@pytest.mark.parametrize(
320+
'max_total_price, max_priority_price, expected_miner_tips',
321+
(
322+
# none of the tip makes it to the miner when the base price matches the txn max price
323+
(10 ** 9, 1, 0),
324+
# half of this tip makes it to the miner because the base price squeezes the tip
325+
(10 ** 9 + 1, 2, 21000),
326+
# the full tip makes it to the miner because the txn max price is exactly big enough
327+
(10 ** 9 + 1, 1, 21000),
328+
# the full tip makes it to the miner, and no more, because the txn max
329+
# price is larger than the sum of the base burn fee and the max tip
330+
(10 ** 9 + 2, 1, 21000),
331+
),
332+
)
333+
def test_eip1559_txn_rewards(
334+
max_total_price,
335+
max_priority_price,
336+
expected_miner_tips,
337+
funded_address,
338+
funded_address_private_key):
339+
340+
chain = build(
341+
MiningChain,
342+
berlin_at(0),
343+
london_at(1), # Start London at block one to get easy 1gwei base fee
344+
disable_pow_check(),
345+
genesis(
346+
params=dict(gas_limit=10**7),
347+
state={funded_address: dict(balance=10**20)},
348+
),
349+
)
350+
vm = chain.get_vm()
351+
txn = new_fee_burn_transaction(
352+
vm,
353+
from_=funded_address,
354+
to=funded_address,
355+
private_key=funded_address_private_key,
356+
max_priority_fee_per_gas=max_priority_price,
357+
max_fee_per_gas=max_total_price,
358+
)
359+
360+
MINER = b'\x0f' * 20
361+
original_balance = vm.state.get_balance(MINER)
362+
chain.mine_all([txn], coinbase=MINER)
363+
new_balance = chain.get_vm().state.get_balance(MINER)
364+
365+
BLOCK_REWARD = 2 * (10 ** 18)
366+
assert original_balance + BLOCK_REWARD + expected_miner_tips == new_balance

0 commit comments

Comments
 (0)