Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EIP-7623 #966

Open
wants to merge 8 commits into
base: forks/prague
Choose a base branch
from
Open
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
47 changes: 37 additions & 10 deletions src/ethereum/prague/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@
state_root,
)
from .transactions import (
FLOOR_CALLDATA_COST,
STANDARD_CALLDATA_TOKEN_COST,
TX_ACCESS_LIST_ADDRESS_COST,
TX_ACCESS_LIST_STORAGE_KEY_COST,
TX_BASE_COST,
TX_CREATE_COST,
TX_DATA_COST_PER_NON_ZERO,
TX_DATA_COST_PER_ZERO,
AccessListTransaction,
BlobTransaction,
FeeMarketTransaction,
Expand Down Expand Up @@ -395,7 +395,9 @@ def check_transaction(
InvalidBlock :
If the transaction is not includable.
"""
if calculate_intrinsic_cost(tx) > tx.gas:
intrinsic_gas, tokens_in_calldata = calculate_intrinsic_cost(tx)
floor = Uint(tokens_in_calldata * FLOOR_CALLDATA_COST + TX_BASE_COST)
if max(intrinsic_gas, floor) > tx.gas:
raise InvalidBlock
if tx.nonce >= 2**64 - 1:
raise InvalidBlock
Expand Down Expand Up @@ -921,7 +923,9 @@ def process_transaction(

effective_gas_fee = tx.gas * env.gas_price

gas = tx.gas - calculate_intrinsic_cost(tx)
intrinsic_gas, tokens_in_calldata = calculate_intrinsic_cost(tx)

gas = tx.gas - intrinsic_gas
increment_nonce(env.state, sender)

sender_balance_after_gas_fee = (
Expand Down Expand Up @@ -964,7 +968,18 @@ def process_transaction(

output = process_message_call(message, env)

# For EIP-7623 gas_used includes the intrinsic costs with the floor price
# for calldata.
gas_used = tx.gas - output.gas_left

# EIP-7623 floor price (note: no EVM costs)

# Transactions with less gas used than the floor pay at the floor cost.
if gas_used < floor:
gas_used = floor
Comment on lines +977 to +979
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a risk here that sender's balance is less than the floor, because we did not charge the floor as part of the intrinsic gas

Copy link

@tanishqjasoria tanishqjasoria Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check against gas limit at the start and user always have enough balance to pay for the gas limit and floor < gas limit for the transaction

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right


output.gas_left = tx.gas - gas_used

gas_refund = min(gas_used // 5, output.refund_counter)
gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price

Expand Down Expand Up @@ -1001,7 +1016,7 @@ def process_transaction(
return total_gas_used, output.logs, output.error


def calculate_intrinsic_cost(tx: Transaction) -> Uint:
def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
"""
Calculates the gas that is charged before execution is started.

Expand All @@ -1023,14 +1038,19 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint:
-------
verified : `ethereum.base_types.Uint`
The intrinsic cost of the transaction.
tokens_in_calldata : `ethereum.base_types.Uint`
The eip-7623 calldata tokens used by the transaction.
"""
data_cost = 0

zero_bytes = 0
for byte in tx.data:
if byte == 0:
data_cost += TX_DATA_COST_PER_ZERO
else:
data_cost += TX_DATA_COST_PER_NON_ZERO
zero_bytes += 1

tokens_in_calldata = zero_bytes + (len(tx.data) - zero_bytes) * 4

data_cost = tokens_in_calldata * STANDARD_CALLDATA_TOKEN_COST

if tx.to == Bytes0(b""):
create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data))))
Expand All @@ -1055,8 +1075,15 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint:
if isinstance(tx, SetCodeTransaction):
auth_cost += PER_EMPTY_ACCOUNT_COST * len(tx.authorizations)

return Uint(
TX_BASE_COST + data_cost + create_cost + access_list_cost + auth_cost
return (
Uint(
TX_BASE_COST
+ data_cost
+ create_cost
+ access_list_cost
+ auth_cost
),
Uint(tokens_in_calldata),
)


Expand Down
4 changes: 2 additions & 2 deletions src/ethereum/prague/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
from .fork_types import Address, Authorization, VersionedHash

TX_BASE_COST = 21000
TX_DATA_COST_PER_NON_ZERO = 16
TX_DATA_COST_PER_ZERO = 4
FLOOR_CALLDATA_COST = 10
STANDARD_CALLDATA_TOKEN_COST = 4
TX_CREATE_COST = 32000
TX_ACCESS_LIST_ADDRESS_COST = 2400
TX_ACCESS_LIST_STORAGE_KEY_COST = 1900
Expand Down
4 changes: 3 additions & 1 deletion whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ Bytes64
Bytes8
Bytes256
Bytes0
calldata
copyreg
copytree
coinbase
coincurve
crypto
E501
EIP
encodings
endian
eth
Expand Down Expand Up @@ -459,4 +461,4 @@ exponentiate
monomial
impl

eoa
eoa