Skip to content

fix(evm): Add MaxFeePerBlobGas validation per EIP-4844#10206

Closed
bshastry wants to merge 2 commits intoNethermindEth:masterfrom
bshastry:fix/blob-gas-validation
Closed

fix(evm): Add MaxFeePerBlobGas validation per EIP-4844#10206
bshastry wants to merge 2 commits intoNethermindEth:masterfrom
bshastry:fix/blob-gas-validation

Conversation

@bshastry
Copy link
Contributor

Changes

  • Add validation to reject blob transactions when tx.MaxFeePerBlobGas < feePerBlobGas
  • Add new TransactionResult.InsufficientMaxFeePerBlobGas error type
  • Add descriptive error message: "max fee per blob gas less than block blob gas fee"
  • Implements EIP-4844 requirement for blob gas price validation

Types of changes

What types of changes does your code introduce?

  • Bugfix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (a change that causes existing functionality not to work as expected)
  • Optimization
  • Refactoring
  • Documentation update
  • Build-related changes
  • Other: Description

Testing

Requires testing

  • Yes
  • No

If yes, did you write tests?

  • Yes
  • No

Notes on testing

Verified using Ethereum execution spec tests (EEST) for EIP-4844 blob transactions. The validation correctly rejects transactions where MaxFeePerBlobGas is insufficient for the current block's blob gas price.

EIP-4844 Specification Reference:

The transaction is invalid if tx.max_fee_per_blob_gas < get_blob_gasprice(block.header)

This change ensures Nethermind properly validates this condition during transaction processing.

Documentation

Requires documentation update

  • Yes
  • No

Requires explanation in Release Notes

  • Yes
  • No

Add validation to reject blob transactions when tx.MaxFeePerBlobGas is
less than the current block's blob gas price (feePerBlobGas).

This implements the EIP-4844 requirement that ensures blob transactions
cannot be included if they're unwilling to pay the current blob gas price.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines +555 to +562
// Check that tx.MaxFeePerBlobGas >= feePerBlobGas (the current blob gas price)
if (validate && BlobGasCalculator.TryCalculateFeePerBlobGas(header, spec.BlobBaseFeeUpdateFraction, out UInt256 feePerBlobGas))
{
if ((UInt256)tx.MaxFeePerBlobGas! < feePerBlobGas)
{
TraceLogInvalidTx(tx, $"INSUFFICIENT_MAX_FEE_PER_BLOB_GAS: tx.MaxFeePerBlobGas ({tx.MaxFeePerBlobGas}) < feePerBlobGas ({feePerBlobGas})");
return TransactionResult.InsufficientMaxFeePerBlobGas;
}
Copy link
Member

Choose a reason for hiding this comment

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

So before we actually go to processing a block (through BlockProcessor and TransactionProcessor) it goes through BlockValidator. We have this validation in BlockValidator.ValidateEip4844Fields.

So having it here is a bit redundant for us.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe the test you are running is not setup properly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm running a statetest using nethtest that doesn't pass through the block validator. Hence this duplication.

Do you have other suggestions so fuzzer can be silenced when blob fee is incorrect and it doesn't flag it as a consensus issue?

Copy link
Contributor

@flcl42 flcl42 Jan 13, 2026

Choose a reason for hiding this comment

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

Let me try to add block validator there

Copy link
Contributor

@flcl42 flcl42 Jan 13, 2026

Choose a reason for hiding this comment

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

Could you share the test please, to confirm it now does not pass?

Copy link
Contributor Author

@bshastry bshastry Jan 13, 2026

Choose a reason for hiding this comment

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

nethtest -m -i test.json for the test below should fail on master (enter the contract call with the stop instruction in the trace) but pass on this branch (no call trace). The stateroot is for this branch's expectation.

{
  "insufficientMaxFeePerBlobGas_EIP4844": {
    "_info": {
      "comment": "Test that blob transactions are rejected when MaxFeePerBlobGas < current blob gas price (EIP-4844)",
      "filling-transition-tool": "Nethermind EVM",
      "description": "This test verifies that a blob transaction with MaxFeePerBlobGas=1 is rejected when the block's excessBlobGas results in feePerBlobGas=2. Without the EIP-4844 MaxFeePerBlobGas validation fix, this transaction would incorrectly be accepted.",
      "url": "https://eips.ethereum.org/EIPS/eip-4844"
    },
    "env": {
      "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
      "currentGasLimit": "0x016345785d8a0000",
      "currentNumber": "0x01",
      "currentTimestamp": "0x03e8",
      "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "currentDifficulty": "0x00",
      "currentBaseFee": "0x01",
      "currentExcessBlobGas": "0x32f0ed"
    },
    "pre": {
      "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
        "nonce": "0x00",
        "balance": "0x0de0b6b3a7640000",
        "code": "0x",
        "storage": {}
      },
      "0x0000000000000000000000000000000000001000": {
        "nonce": "0x00",
        "balance": "0x00",
        "code": "0x00",
        "storage": {}
      }
    },
    "transaction": {
      "type": "0x03",
      "nonce": "0x00",
      "maxPriorityFeePerGas": "0x01",
      "maxFeePerGas": "0x01",
      "gasLimit": [
        "0x5208"
      ],
      "to": "0x0000000000000000000000000000000000001000",
      "value": [
        "0x00"
      ],
      "data": [
        "0x"
      ],
      "maxFeePerBlobGas": "0x01",
      "blobVersionedHashes": [
        "0x0100000000000000000000000000000000000000000000000000000000000000"
      ],
      "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
      "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
    },
    "post": {
      "Cancun": [
        {
          "expectException": "TR_InsufficientMaxFeePerBlobGas",
          "hash": "0x44b4804a96216f31b8d08d1ddb86f7b624c4bc0c0ad986cfedf18ea8d4a3c1da",
          "logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
          "indexes": {
            "data": 0,
            "gas": 0,
            "value": 0
          }
        }
      ]
    }
  }
}

@LukaszRozmej
Copy link
Member

Close in favor of #10224

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.

3 participants

Comments