@@ -140,6 +140,8 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts:
140140 G_MEMORY = 3 ,
141141 G_TX_DATA_ZERO = 4 ,
142142 G_TX_DATA_NON_ZERO = 68 ,
143+ G_TX_DATA_STANDARD_TOKEN_COST = 0 ,
144+ G_TX_DATA_FLOOR_TOKEN_COST = 0 ,
143145 G_TRANSACTION = 21_000 ,
144146 G_TRANSACTION_CREATE = 32_000 ,
145147 G_LOG = 375 ,
@@ -184,7 +186,7 @@ def calldata_gas_calculator(
184186 """
185187 gas_costs = cls .gas_costs (block_number , timestamp )
186188
187- def fn (* , data : BytesConvertible ) -> int :
189+ def fn (* , data : BytesConvertible , floor : bool = False ) -> int :
188190 cost = 0
189191 for b in Bytes (data ):
190192 if b == 0 :
@@ -211,6 +213,7 @@ def fn(
211213 contract_creation : bool = False ,
212214 access_list : List [AccessList ] | None = None ,
213215 authorization_list_or_count : Sized | int | None = None ,
216+ return_cost_deducted_prior_execution : bool = False ,
214217 ) -> int :
215218 assert access_list is None , f"Access list is not supported in { cls .name ()} "
216219 assert (
@@ -633,6 +636,7 @@ def fn(
633636 contract_creation : bool = False ,
634637 access_list : List [AccessList ] | None = None ,
635638 authorization_list_or_count : Sized | int | None = None ,
639+ return_cost_deducted_prior_execution : bool = False ,
636640 ) -> int :
637641 intrinsic_cost : int = super_fn (
638642 calldata = calldata ,
@@ -764,7 +768,7 @@ def valid_opcodes(
764768 @classmethod
765769 def gas_costs (cls , block_number : int = 0 , timestamp : int = 0 ) -> GasCosts :
766770 """
767- Returns a dataclass with the defined gas costs constants for genesis .
771+ On Istanbul, the non-zero transaction data byte cost is reduced to 16 due to EIP-2028 .
768772 """
769773 return replace (
770774 super (Istanbul , cls ).gas_costs (block_number , timestamp ),
@@ -818,6 +822,7 @@ def fn(
818822 contract_creation : bool = False ,
819823 access_list : List [AccessList ] | None = None ,
820824 authorization_list_or_count : Sized | int | None = None ,
825+ return_cost_deducted_prior_execution : bool = False ,
821826 ) -> int :
822827 intrinsic_cost : int = super_fn (
823828 calldata = calldata ,
@@ -1127,6 +1132,17 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]
11271132 block_number , timestamp
11281133 )
11291134
1135+ @classmethod
1136+ def gas_costs (cls , block_number : int = 0 , timestamp : int = 0 ) -> GasCosts :
1137+ """
1138+ On Prague, the standard token cost and the floor token costs are introduced due to EIP-7623
1139+ """
1140+ return replace (
1141+ super (Prague , cls ).gas_costs (block_number , timestamp ),
1142+ G_TX_DATA_STANDARD_TOKEN_COST = 4 , # https://eips.ethereum.org/EIPS/eip-7623
1143+ G_TX_DATA_FLOOR_TOKEN_COST = 10 ,
1144+ )
1145+
11301146 @classmethod
11311147 def system_contracts (cls , block_number : int = 0 , timestamp : int = 0 ) -> List [Address ]:
11321148 """
@@ -1146,6 +1162,29 @@ def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int:
11461162 """
11471163 return 2
11481164
1165+ @classmethod
1166+ def calldata_gas_calculator (
1167+ cls , block_number : int = 0 , timestamp : int = 0
1168+ ) -> CalldataGasCalculator :
1169+ """
1170+ Returns a callable that calculates the transaction gas cost for its calldata
1171+ depending on its contents.
1172+ """
1173+ gas_costs = cls .gas_costs (block_number , timestamp )
1174+
1175+ def fn (* , data : BytesConvertible , floor : bool = False ) -> int :
1176+ tokens = 0
1177+ for b in Bytes (data ):
1178+ if b == 0 :
1179+ tokens += 1
1180+ else :
1181+ tokens += 4
1182+ if floor :
1183+ return tokens * gas_costs .G_TX_DATA_FLOOR_TOKEN_COST
1184+ return tokens * gas_costs .G_TX_DATA_STANDARD_TOKEN_COST
1185+
1186+ return fn
1187+
11491188 @classmethod
11501189 def transaction_intrinsic_cost_calculator (
11511190 cls , block_number : int = 0 , timestamp : int = 0
@@ -1164,17 +1203,24 @@ def fn(
11641203 contract_creation : bool = False ,
11651204 access_list : List [AccessList ] | None = None ,
11661205 authorization_list_or_count : Sized | int | None = None ,
1206+ return_cost_deducted_prior_execution : bool = False ,
11671207 ) -> int :
11681208 intrinsic_cost : int = super_fn (
11691209 calldata = calldata ,
11701210 contract_creation = contract_creation ,
11711211 access_list = access_list ,
1212+ return_cost_deducted_prior_execution = False ,
11721213 )
11731214 if authorization_list_or_count is not None :
11741215 if isinstance (authorization_list_or_count , Sized ):
11751216 authorization_list_or_count = len (authorization_list_or_count )
11761217 intrinsic_cost += authorization_list_or_count * gas_costs .G_AUTHORIZATION
1177- return intrinsic_cost
1218+
1219+ if return_cost_deducted_prior_execution :
1220+ return intrinsic_cost
1221+
1222+ floor_data_cost = cls .calldata_gas_calculator ()(data = calldata , floor = True )
1223+ return max (intrinsic_cost , floor_data_cost + gas_costs .G_TRANSACTION )
11781224
11791225 return fn
11801226
0 commit comments