Skip to content

Align EVM fee accounting with wei-denominated base fees#5420

Merged
sacherjj merged 1 commit into
casper-network:feat-evmfrom
mpapierski:evm-motes-to-wei-costs
Jun 24, 2026
Merged

Align EVM fee accounting with wei-denominated base fees#5420
sacherjj merged 1 commit into
casper-network:feat-evmfrom
mpapierski:evm-motes-to-wei-costs

Conversation

@mpapierski

@mpapierski mpapierski commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR fixes EVM gas fee denomination across Casper’s mote-based accounting and Ethereum’s wei-based gas-price model.

Casper accounts and fee/refund handling operate in motes:

1 CSPR = 10^9 motes

Ethereum gas prices operate in wei:

1 ETH = 10^18 wei

To bridge the two:

1 mote = 10^9 wei

The PR introduces an explicit [evm].wei_per_mote chainspec value and uses it to scale Casper’s EVM base fee into Ethereum-visible wei, then convert consumed EVM gas fees back into motes for Casper balance accounting.

Ethereum Fee Background

Ethereum’s EVM uses gas prices denominated in wei per gas.

For the transaction variants currently supported:

  • Legacy/type 0 and EIP-2930/type 1 use a fixed gas_price.
  • EIP-1559/type 2 and EIP-7702/type 4 use dynamic-fee fields:
    • max_fee_per_gas
    • max_priority_fee_per_gas

Under EIP-1559-style rules, the effective gas price is:

effective_gas_price = min(max_fee_per_gas, base_fee + max_priority_fee_per_gas)

The BASEFEE opcode returns the current block base fee, also denominated in wei.

Relevant specs:

Casper Policy Difference

Casper currently does not prioritize EVM transactions by gas-price bidding. Therefore, accepting a fixed-price EVM overbid would charge the user more without giving them any scheduling benefit.

This PR makes that explicit:

Legacy / EIP-2930:
gas_price == base_fee_wei

Dynamic-fee transactions still use max_fee_per_gas as a sender cap, but priority fees are rejected:

EIP-1559 / EIP-7702:
max_fee_per_gas >= base_fee_wei
max_priority_fee_per_gas == 0

This may be revisited later if we introduce EVM gas-price-aware transaction ordering to be closer to the ETH mainnet transaction handling.

Implementation

[evm].base_fee remains a chainspec policy value denominated in motes per EVM gas.

A new chainspec field defines the conversion ratio:

[evm]
base_fee = 1_000_000
wei_per_mote = 1_000_000_000

Runtime derives the EVM-visible base fee as:

base_fee_wei = base_fee * wei_per_mote

That wei-denominated value is used for:

  • EVM transaction config compliance.
  • revm block context basefee.
  • BASEFEE opcode behavior.
  • receipt effectiveGasPrice.

After EVM execution, fees are converted back into motes:

fee_motes = ceil(gas_used * effective_gas_price_wei / wei_per_mote)

The ceil is intentional because balances cannot represent fractional motes. Any non-zero sub-mote EVM fee is charged as one mote.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm for now; we can refine if necessary as we move forward

@zajko

zajko commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In Transaction we have a function gas_cost and for EVM it returns EvmTransaction::gas_limit * EvmTransaction::max_fee_per_gas but EvmTransaction::gas_limit is inputted by the user and it represents the "wei motes" not "casper motes", right? I'm not sure if that's aligned.

Comment thread AGENTS.md
@@ -0,0 +1,6 @@
# AGENTS.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this a universal solution? Should all/most/some AI solutions work with this file?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, pretty much a standardized file. All major coding agents respect it, to my knowledge - https://agents.md/

@mpapierski

Copy link
Copy Markdown
Collaborator Author

In Transaction we have a function gas_cost and for EVM it returns EvmTransaction::gas_limit * EvmTransaction::max_fee_per_gas but EvmTransaction::gas_limit is inputted by the user and it represents the "wei motes" not "casper motes", right? I'm not sure if that's aligned.

gas_limit itself is not denominated in wei or motes; it is the EVM gas-unit limit supplied by the transaction. The wei-denominated part is the gas price, i.e. max_fee_per_gas / effective gas price. For EVM transactions, we calculate the maximum fee as gas_limit * effective_gas_price_wei, then convert the resulting wei total back to Casper motes using ceil(total_wei / wei_per_mote). So Transaction::gas_cost still returns motes, but for EVM it goes through the EVM conversion path instead of assuming a 1:1 gas-to-mote relation.

@sacherjj sacherjj merged commit 32860cb into casper-network:feat-evm Jun 24, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants