Skip to content

Commit ec920db

Browse files
authored
EIP-3529 fixes (#2026)
* Calculate gas_used in frontier vm initialization, use MAX_REFUND_QUOTIENT throughout * Standardize make_receipt between Berlin and Byzantium
1 parent 8a1ce83 commit ec920db

File tree

7 files changed

+45
-60
lines changed

7 files changed

+45
-60
lines changed

eth/vm/forks/berlin/__init__.py

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,10 @@
22
Type,
33
)
44

5-
from eth.abc import (
6-
BlockHeaderAPI,
7-
ComputationAPI,
8-
ReceiptAPI,
9-
SignedTransactionAPI,
10-
StateAPI,
11-
)
125
from eth.rlp.blocks import BaseBlock
136
from eth.vm.forks import (
147
MuirGlacierVM,
158
)
16-
from eth.vm.forks.byzantium.constants import (
17-
EIP658_TRANSACTION_STATUS_CODE_FAILURE,
18-
EIP658_TRANSACTION_STATUS_CODE_SUCCESS,
19-
)
209
from eth.vm.state import BaseState
2110

2211
from .blocks import BerlinBlock
@@ -28,17 +17,6 @@
2817
from .state import BerlinState
2918

3019

31-
def finalize_gas_used(transaction: SignedTransactionAPI, computation: ComputationAPI) -> int:
32-
gas_remaining = computation.get_gas_remaining()
33-
consumed_gas = transaction.gas - gas_remaining
34-
35-
gross_refund = computation.get_gas_refund()
36-
max_refund = consumed_gas // 2
37-
gas_refund = min(gross_refund, max_refund)
38-
39-
return consumed_gas - gas_refund
40-
41-
4220
class BerlinVM(MuirGlacierVM):
4321
# fork name
4422
fork = 'berlin'
@@ -51,19 +29,3 @@ class BerlinVM(MuirGlacierVM):
5129
create_header_from_parent = staticmethod(create_berlin_header_from_parent) # type: ignore
5230
compute_difficulty = staticmethod(compute_berlin_difficulty) # type: ignore
5331
configure_header = configure_berlin_header
54-
55-
@staticmethod
56-
def make_receipt(
57-
base_header: BlockHeaderAPI,
58-
transaction: SignedTransactionAPI,
59-
computation: ComputationAPI,
60-
state: StateAPI) -> ReceiptAPI:
61-
62-
gas_used = base_header.gas_used + finalize_gas_used(transaction, computation)
63-
64-
if computation.is_error:
65-
status_code = EIP658_TRANSACTION_STATUS_CODE_FAILURE
66-
else:
67-
status_code = EIP658_TRANSACTION_STATUS_CODE_SUCCESS
68-
69-
return transaction.make_receipt(status_code, gas_used, computation.get_log_entries())

eth/vm/forks/byzantium/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
validate_lte,
2929
)
3030
from eth.vm.forks.spurious_dragon import SpuriousDragonVM
31-
from eth.vm.forks.frontier import make_frontier_receipt
3231

3332
from .blocks import ByzantiumBlock
3433
from .constants import (
@@ -100,18 +99,19 @@ def add_receipt_to_header(self,
10099
gas_used=receipt.gas_used,
101100
)
102101

103-
@staticmethod
102+
@classmethod
104103
def make_receipt(
104+
cls,
105105
base_header: BlockHeaderAPI,
106106
transaction: SignedTransactionAPI,
107107
computation: ComputationAPI,
108108
state: StateAPI) -> ReceiptAPI:
109109

110-
receipt_without_state_root = make_frontier_receipt(base_header, transaction, computation)
110+
gas_used = base_header.gas_used + cls.finalize_gas_used(transaction, computation)
111111

112112
if computation.is_error:
113113
status_code = EIP658_TRANSACTION_STATUS_CODE_FAILURE
114114
else:
115115
status_code = EIP658_TRANSACTION_STATUS_CODE_SUCCESS
116116

117-
return receipt_without_state_root.copy(state_root=status_code)
117+
return transaction.make_receipt(status_code, gas_used, computation.get_log_entries())

eth/vm/forks/frontier/__init__.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from eth.vm.base import VM
2626

2727
from .blocks import FrontierBlock
28+
from .constants import MAX_REFUND_QUOTIENT
2829
from .state import FrontierState
2930
from .headers import (
3031
create_frontier_header_from_parent,
@@ -34,9 +35,8 @@
3435
from .validation import validate_frontier_transaction_against_header
3536

3637

37-
def make_frontier_receipt(base_header: BlockHeaderAPI,
38-
transaction: SignedTransactionAPI,
39-
computation: ComputationAPI) -> ReceiptAPI:
38+
def make_frontier_receipt(computation: ComputationAPI,
39+
new_cumulative_gas_used: int) -> ReceiptAPI:
4040
# Reusable for other forks
4141
# This skips setting the state root (set to 0 instead). The logic for making a state root
4242
# lives in the FrontierVM, so that state merkelization at each receipt is skipped at Byzantium+.
@@ -47,19 +47,9 @@ def make_frontier_receipt(base_header: BlockHeaderAPI,
4747
in computation.get_log_entries()
4848
]
4949

50-
gas_remaining = computation.get_gas_remaining()
51-
gas_refund = computation.get_gas_refund()
52-
tx_gas_used = (
53-
transaction.gas - gas_remaining
54-
) - min(
55-
gas_refund,
56-
(transaction.gas - gas_remaining) // 2,
57-
)
58-
gas_used = base_header.gas_used + tx_gas_used
59-
6050
receipt = Receipt(
6151
state_root=ZERO_HASH32,
62-
gas_used=gas_used,
52+
gas_used=new_cumulative_gas_used,
6353
logs=logs,
6454
)
6555

@@ -103,14 +93,35 @@ def add_receipt_to_header(self,
10393
state_root=self.state.make_state_root(),
10494
)
10595

106-
@staticmethod
96+
@classmethod
97+
def calculate_net_gas_refund(cls, consumed_gas: int, gross_refund: int) -> int:
98+
max_refund = consumed_gas // MAX_REFUND_QUOTIENT
99+
return min(max_refund, gross_refund)
100+
101+
@classmethod
102+
def finalize_gas_used(cls,
103+
transaction: SignedTransactionAPI,
104+
computation: ComputationAPI) -> int:
105+
106+
gas_remaining = computation.get_gas_remaining()
107+
consumed_gas = transaction.gas - gas_remaining
108+
109+
gross_refund = computation.get_gas_refund()
110+
net_refund = cls.calculate_net_gas_refund(consumed_gas, gross_refund)
111+
112+
return consumed_gas - net_refund
113+
114+
@classmethod
107115
def make_receipt(
116+
cls,
108117
base_header: BlockHeaderAPI,
109118
transaction: SignedTransactionAPI,
110119
computation: ComputationAPI,
111120
state: StateAPI) -> ReceiptAPI:
112121

113-
receipt_without_state_root = make_frontier_receipt(base_header, transaction, computation)
122+
gas_used = base_header.gas_used + cls.finalize_gas_used(transaction, computation)
123+
124+
receipt_without_state_root = make_frontier_receipt(computation, gas_used)
114125

115126
return receipt_without_state_root.copy(
116127
state_root=state.make_state_root()

eth/vm/forks/frontier/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
FRONTIER_DIFFICULTY_ADJUSTMENT_CUTOFF = 13
22
REFUND_SELFDESTRUCT = 24000
3+
4+
MAX_REFUND_QUOTIENT = 2

eth/vm/forks/frontier/state.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535

3636

3737
from .computation import FrontierComputation
38-
from .constants import REFUND_SELFDESTRUCT
38+
from .constants import (
39+
REFUND_SELFDESTRUCT,
40+
MAX_REFUND_QUOTIENT,
41+
)
3942
from .transaction_context import (
4043
FrontierTransactionContext
4144
)
@@ -154,7 +157,7 @@ def calculate_gas_refund(cls,
154157
# Gas Refunds
155158
gas_refunded = computation.get_gas_refund()
156159

157-
return min(gas_refunded, gas_used // 2)
160+
return min(gas_refunded, gas_used // MAX_REFUND_QUOTIENT)
158161

159162
def finalize_computation(self,
160163
transaction: SignedTransactionAPI,

eth/vm/forks/london/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from .blocks import LondonBlock
1414
from .constants import (
15+
EIP3529_MAX_REFUND_QUOTIENT,
1516
ELASTICITY_MULTIPLIER,
1617
)
1718
from .headers import (
@@ -59,3 +60,8 @@ def validate_gas(
5960
f"Header has invalid base fee per gas (has {header.base_fee_per_gas}"
6061
f", expected {expected_base_fee_per_gas})"
6162
)
63+
64+
@classmethod
65+
def calculate_net_gas_refund(cls, consumed_gas: int, gross_refund: int) -> int:
66+
max_refund = consumed_gas // EIP3529_MAX_REFUND_QUOTIENT
67+
return min(max_refund, gross_refund)

newsfragments/2026.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add EIP-3529 refund reduction to make_receipt logic.

0 commit comments

Comments
 (0)