Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

fix: reject transaction if maxFeePerGas is less than blockBaseFeePerGas of the pending block #2840

Closed
wants to merge 3 commits into from

Conversation

jeffsmale90
Copy link
Contributor

@jeffsmale90 jeffsmale90 commented Apr 6, 2022

Fixes #2176

@jeffsmale90 jeffsmale90 marked this pull request as ready for review April 7, 2022 09:40
@davidmurdoch davidmurdoch force-pushed the develop branch 3 times, most recently from 96d6c7f to 47d583d Compare April 8, 2022 17:42
@davidmurdoch
Copy link
Member

Can you rebase this on current develop?

Copy link
Contributor

@MicaiahReid MicaiahReid left a comment

Choose a reason for hiding this comment

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

So with further testing I discovered that transactions with too small gas price were accepted if the gas limit is specified. I opened an issue with Geth, and they pretty much said it's expected behavior. Here is a summary of how they handle these cases and their reasoning:

Gas Limit Gas Price Result Notes
Unspecified Unspecified No error Geth chooses a good gas price, then uses that price to estimate gas limit.
Specified < baseFeePerGas No error Geth blindly accepts the gas price because the transaction has a gas limit.
Unspecified < baseFeePerGas Error: maxFeePerGas is less than block base fee. Because no gas limit was specified, Geth needs to estimate it. To estimate it, it runs the transaction against the next block. Because the gas price is too low, it's rejected.

I think the key difference between us and Geth in this case is that our eth_estimateGas function does not enforce a baseFeePerGas. This can be seen when we make the RuntimeBlock in eth_estimateGas:

const block = new RuntimeBlock(
  Quantity.from((parentHeader.number.toBigInt() || 0n) + 1n),
  parentHeader.parentHash,
  parentHeader.miner,
  tx.gas.toBuffer(),
  parentHeader.gasUsed.toBuffer(),
  parentHeader.timestamp,
  options.miner.difficulty,
  parentHeader.totalDifficulty,
  0n // no baseFeePerGas for estimates
);

So I think rather than this current change, we may just want to pass in the next block's baseFeePerGas rather than 0n. Thoughts? @davidmurdoch @jeffsmale90

@MicaiahReid
Copy link
Contributor

MicaiahReid commented Apr 20, 2022

Upon further inspection, it doesn't look like we call eth_estimateGas as liberally as Geth does. We only estimate gas for transactions that omit gasLimit if their --miner.defaultTransactionGasLimit="estimate", so my suggested fix wouldn't work in all cases.

Regardless, the current implementation now rejects the transaction in more cases than Geth. In my eyes, we could:

  1. Match Geth exactly by setting the baseFeePerGas in the eth_estimateGas function as mentioned above, and checking that the gas price is greater than the baseFeePerGas in the autofillDefaultTransactionValues branch that uses the default gas limit.
  2. Add a --chain.mode="geth" option that allows a user to use ganache in a more strict mode (following geth's rules) and a more lenient mode (we don't ever error for gas being too low).
  3. Leave ganache as is to be more lenient and, in our eyes, intuitive.

@davidmurdoch davidmurdoch force-pushed the develop branch 5 times, most recently from 892c68f to 0e9642f Compare April 22, 2022 19:52
@jeffsmale90
Copy link
Contributor Author

@MicaiahReid @davidmurdoch I think the best way forward is to discard this change, and consider adding a strict "Geth" mode as @MicaiahReid recommended where we pass the actual next block baseFeePerGas into vm.runTx (instead of 0).

What do you guys think?

@MicaiahReid
Copy link
Contributor

@jeffsmale90 I'm on board for that!
I think in all the actions would be:

@davidmurdoch thoughts?

@davidmurdoch
Copy link
Member

@MicaiahReid That sounds like a great plan to me!

@jeffsmale90
Copy link
Contributor Author

Closing this PR, after following the actions @MicaiahReid listed above.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

In Geth chain-mode, logic to accept/reject transactions based on gas price/limit should match Geth
3 participants