Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,10 @@ def _compute_deploy_gas_limit(
sstore_state_gas = sstore.state_cost(fork)
sstore_regular_gas = sstore.gas_cost(fork) - sstore_state_gas

# Back out the state gas folded into TX_CREATE.
intrinsic_state_gas = fork.transaction_intrinsic_state_gas(
contract_creation=True
)
intrinsic_regular_gas = (
intrinsic_gas_calculator(calldata=initcode, contract_creation=True)
- intrinsic_state_gas
# The intrinsic cost is now regular-only: the created account's
# NEW_ACCOUNT state gas is charged at the top frame, not folded in.
intrinsic_regular_gas = intrinsic_gas_calculator(
calldata=initcode, contract_creation=True
)

# Regular portion, bound by the gas cap.
Expand All @@ -274,8 +271,7 @@ def _compute_deploy_gas_limit(
regular_gas *= 2

# State portion, from the block reservoir.
state_gas = intrinsic_state_gas
state_gas += fork.code_deposit_state_gas(code_size=deploy_code_size)
state_gas = fork.code_deposit_state_gas(code_size=deploy_code_size)
state_gas += storage_slots * sstore_state_gas

deploy_gas_limit = regular_gas + state_gas
Expand Down
11 changes: 0 additions & 11 deletions packages/testing/src/execution_testing/forks/base_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,17 +767,6 @@ def transaction_intrinsic_cost_calculator(
"""
pass

@classmethod
def transaction_intrinsic_state_gas(
cls,
*,
contract_creation: bool = False,
authorization_count: int = 0,
) -> int:
"""Return intrinsic state gas (zero pre-Amsterdam)."""
del contract_creation, authorization_count
return 0

@classmethod
def transaction_top_frame_gas_calculator(
cls,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,28 +127,6 @@ def fn(

return fn

@classmethod
def transaction_intrinsic_state_gas(
cls,
*,
contract_creation: bool = False,
authorization_count: int = 0,
) -> int:
"""
Return the intrinsic state gas for a transaction.

Under EIP-2780 neither authorizations nor contract creation
contribute intrinsic state gas: the authority account-creation
and delegation-write costs and the created account's
``NEW_ACCOUNT`` are all state-dependent and charged at the top
frame instead.
"""
del contract_creation, authorization_count
return super(EIP2780, cls).transaction_intrinsic_state_gas(
contract_creation=False,
authorization_count=0,
)

@classmethod
def transaction_top_frame_gas_calculator(
cls,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,30 +232,6 @@ def fn(opcode: OpcodeBase) -> int:

return fn

@classmethod
def transaction_intrinsic_state_gas(
cls,
*,
contract_creation: bool = False,
authorization_count: int = 0,
) -> int:
"""
Return the intrinsic state gas for a transaction. Creation
adds `STATE_BYTES_PER_NEW_ACCOUNT * cpsb`, and each
authorization adds
`(STATE_BYTES_PER_NEW_ACCOUNT + STATE_BYTES_PER_AUTH_BASE) * cpsb`.
"""
cpsb = cls.cost_per_state_byte()
state_gas = 0
if contract_creation:
state_gas += STATE_BYTES_PER_NEW_ACCOUNT * cpsb
state_gas += (
(STATE_BYTES_PER_NEW_ACCOUNT + STATE_BYTES_PER_AUTH_BASE)
* cpsb
* authorization_count
)
return state_gas

@classmethod
def _calculate_sstore_state_gas(
cls, opcode: OpcodeBase, gas_costs: GasCosts
Expand Down
14 changes: 3 additions & 11 deletions src/ethereum/forks/amsterdam/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,8 +806,6 @@ def process_unchecked_system_transaction(
authorizations=(),
index_in_block=None,
tx_hash=None,
intrinsic_regular_gas=Uint(0),
intrinsic_state_gas=Uint(0),
)

system_tx_message = Message(
Expand Down Expand Up @@ -1034,7 +1032,7 @@ def process_transaction(
sender = recover_sender(tx)
intrinsic = validate_transaction(tx, sender)

intrinsic_gas = Uint(intrinsic.regular) + Uint(intrinsic.state)
intrinsic_gas = Uint(intrinsic.regular)

(
effective_gas_price,
Expand Down Expand Up @@ -1098,15 +1096,9 @@ def process_transaction(
authorizations=authorizations,
index_in_block=index,
tx_hash=get_transaction_hash(encode_transaction(tx)),
intrinsic_regular_gas=intrinsic.regular,
intrinsic_state_gas=intrinsic.state,
)

message = prepare_message(
block_env,
tx_env,
tx,
)
message = prepare_message(block_env, tx_env, tx)

tx_output = process_message_call(message)

Expand Down Expand Up @@ -1135,7 +1127,7 @@ def process_transaction(
# transfer miner fees
create_ether(tx_state, block_env.coinbase, U256(transaction_fee))

tx_state_gas = int(tx_env.intrinsic_state_gas) + tx_output.state_gas_used
tx_state_gas = tx_output.state_gas_used
tx_regular_gas = tx_gas_used_before_refund - Uint(max(0, tx_state_gas))
block_output.block_gas_used += tx_regular_gas
block_output.block_state_gas_used += Uint(max(0, tx_state_gas))
Expand Down
63 changes: 19 additions & 44 deletions src/ethereum/forks/amsterdam/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@
InitCodeTooLargeError,
TransactionTypeError,
)
from .fork_types import (
Authorization,
RegularGas,
StateGas,
VersionedHash,
)
from .fork_types import Authorization, RegularGas, VersionedHash


@final
Expand All @@ -41,14 +36,6 @@ class IntrinsicGasCost:
regular: RegularGas
"""Regular execution gas (calldata, base cost, access list, etc.)."""

state: StateGas
"""
State growth gas (account creation, storage set, authorization) per
[EIP-8037].

[EIP-8037]: https://eips.ethereum.org/EIPS/eip-8037
"""

calldata_floor: RegularGas
"""
Minimum gas cost based on calldata size per [EIP-7623].
Expand Down Expand Up @@ -610,7 +597,7 @@ def validate_transaction(tx: Transaction, sender: Address) -> IntrinsicGasCost:
from .vm.interpreter import MAX_INIT_CODE_SIZE

intrinsic = calculate_intrinsic_cost(tx, sender)
intrinsic_gas = Uint(intrinsic.regular) + Uint(intrinsic.state)
intrinsic_gas = Uint(intrinsic.regular)
if intrinsic_gas > tx.gas:
raise InsufficientTransactionGasError("Insufficient intrinsic gas")
if intrinsic.calldata_floor > tx.gas:
Expand Down Expand Up @@ -665,13 +652,10 @@ def calculate_intrinsic_cost(
charges.

This function takes a transaction and gas_limit as parameters and
returns the intrinsic regular gas cost, intrinsic state gas cost, and the
minimum gas cost used by the transaction based on the calldata size.
returns the intrinsic regular gas cost and the minimum gas cost used by
the transaction based on the calldata size.
"""
from .vm.gas import (
GasCosts,
init_code_cost,
)
from .vm.gas import GasCosts, init_code_cost

tokens_in_calldata = count_tokens_in_data(tx.data)

Expand All @@ -680,18 +664,15 @@ def calculate_intrinsic_cost(
is_create = tx.to == Bytes0(b"")
is_self_transfer = tx.to == sender

recipient_regular_gas = Uint(0)
recipient_state_gas = Uint(0)
recipient_gas = Uint(0)
if is_create:
recipient_regular_gas = GasCosts.CREATE_ACCESS + init_code_cost(
ulen(tx.data)
)
recipient_gas = GasCosts.CREATE_ACCESS + init_code_cost(ulen(tx.data))
if tx.value > U256(0):
recipient_regular_gas += GasCosts.TRANSFER_LOG_COST
recipient_gas += GasCosts.TRANSFER_LOG_COST
elif not is_self_transfer:
recipient_regular_gas = GasCosts.COLD_ACCOUNT_ACCESS
recipient_gas = GasCosts.COLD_ACCOUNT_ACCESS
if tx.value > U256(0):
recipient_regular_gas += (
recipient_gas += (
GasCosts.TRANSFER_LOG_COST + GasCosts.TX_VALUE_COST
)

Expand All @@ -711,10 +692,9 @@ def calculate_intrinsic_cost(
# Data token floor cost for access list bytes.
access_list_cost += tokens_in_access_list * GasCosts.TX_DATA_TOKEN_FLOOR

auth_regular_gas = Uint(0)
auth_state_gas = Uint(0)
auth_cost = Uint(0)
if isinstance(tx, SetCodeTransaction):
auth_regular_gas = GasCosts.REGULAR_PER_AUTH_BASE_COST * ulen(
auth_cost = GasCosts.REGULAR_PER_AUTH_BASE_COST * ulen(
tx.authorizations
)

Expand All @@ -729,19 +709,14 @@ def calculate_intrinsic_cost(
total_floor_tokens * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE
)

intrinsic_regular_gas = (
GasCosts.TX_BASE
+ data_cost
+ recipient_regular_gas
+ access_list_cost
+ auth_regular_gas
)

intrinsic_state_gas = recipient_state_gas + auth_state_gas

return IntrinsicGasCost(
regular=RegularGas(intrinsic_regular_gas),
state=StateGas(intrinsic_state_gas),
regular=RegularGas(
GasCosts.TX_BASE
+ data_cost
+ recipient_gas
+ access_list_cost
+ auth_cost
),
calldata_floor=RegularGas(data_floor_gas_cost),
)

Expand Down
2 changes: 0 additions & 2 deletions src/ethereum/forks/amsterdam/vm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ class TransactionEnvironment:
authorizations: Tuple[Authorization, ...]
index_in_block: Optional[Uint]
tx_hash: Optional[Hash32]
intrinsic_regular_gas: Uint
intrinsic_state_gas: Uint


@final
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,6 @@ def test_create_tx_below_total_intrinsic(
contract_creation=True,
calldata=bytes(initcode),
)
assert fork.transaction_intrinsic_state_gas(contract_creation=True) == 0, (
"creation intrinsic is regular-only under EIP-2780"
)

tx = Transaction(
to=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ def test_sstore_via_delegation_pointer(
contract code in the EOA's context. The SSTORE state gas should
be charged from the reservoir just as it would for a direct call.
"""
auth_state_gas = fork.transaction_intrinsic_state_gas(
authorization_count=1,
)
sstore_state_gas = Op.SSTORE(new_value=1).state_cost(fork)

storage = Storage()
Expand All @@ -54,17 +51,25 @@ def test_sstore_via_delegation_pointer(
# EOA with pre-existing delegation to the contract
delegator = pre.fund_eoa(delegation=contract)

# The authorization re-targets an already-delegated authority whose
# nonce (1, from the delegation setup) no longer matches nonce=0, so
# it is invalid and charges no top-frame state gas.
authorization = AuthorizationTuple(
address=contract,
nonce=0,
signer=delegator,
creates_account=False,
writes_delegation=False,
first_write=False,
)
auth_state_gas = fork.transaction_top_frame_state_gas(
authorizations=[authorization]
)
sender = pre.fund_eoa()
tx = Transaction(
to=delegator,
state_gas_reservoir=auth_state_gas + sstore_state_gas,
authorization_list=[
AuthorizationTuple(
address=contract,
nonce=0,
signer=delegator,
),
],
authorization_list=[authorization],
sender=sender,
)

Expand Down Expand Up @@ -117,12 +122,9 @@ def test_delegation_pointer_new_account_state_gas(
is charged identically to a direct call.
"""
gas_costs = fork.gas_costs()
auth_state_gas = fork.transaction_intrinsic_state_gas(
authorization_count=1,
)
new_account_state_gas = gas_costs.NEW_ACCOUNT

target = 0xDEAD
target = pre.nonexistent_account()

parent_storage = Storage()
contract = pre.deploy_contract(
Expand All @@ -138,17 +140,26 @@ def test_delegation_pointer_new_account_state_gas(
# EOA delegates to the contract
delegator = pre.fund_eoa(delegation=contract, amount=1)

# The authorization re-targets an already-delegated authority whose
# nonce (1, from the delegation setup) no longer matches nonce=0, so
# it is invalid and charges no top-frame state gas.
authorization = AuthorizationTuple(
address=contract,
nonce=0,
signer=delegator,
creates_account=False,
writes_delegation=False,
first_write=False,
)
auth_state_gas = fork.transaction_top_frame_state_gas(
authorizations=[authorization]
)

sender = pre.fund_eoa()
tx = Transaction(
to=delegator,
state_gas_reservoir=auth_state_gas + new_account_state_gas,
authorization_list=[
AuthorizationTuple(
address=contract,
nonce=0,
signer=delegator,
),
],
authorization_list=[authorization],
sender=sender,
)

Expand Down
Loading
Loading