Fix(rpc) Effective gas_price for simulations (#6722)

This commit is contained in:
AtomicAzzaz
2024-02-22 16:28:59 +04:00
committed by GitHub
parent a272bbb76b
commit 9c7b2b5f18

View File

@ -1,5 +1,7 @@
//! utilities for working with revm
use std::cmp::min;
use crate::eth::error::{EthApiError, EthResult, RpcInvalidTransactionError};
#[cfg(feature = "optimism")]
use reth_primitives::revm::env::fill_op_tx_env;
@ -438,9 +440,6 @@ pub(crate) struct CallFees {
impl CallFees {
/// Ensures the fields of a [TransactionRequest] are not conflicting.
///
/// If no `gasPrice` or `maxFeePerGas` is set, then the `gas_price` in the returned `gas_price`
/// will be `0`. See: <https://github.com/ethereum/go-ethereum/blob/2754b197c935ee63101cbbca2752338246384fec/internal/ethapi/transaction_args.go#L242-L255>
///
/// # EIP-4844 transactions
///
/// Blob transactions have an additional fee parameter `maxFeePerBlobGas`.
@ -458,21 +457,38 @@ impl CallFees {
max_fee_per_blob_gas: Option<U256>,
block_blob_fee: Option<U256>,
) -> EthResult<CallFees> {
/// Ensures that the transaction's max fee is lower than the priority fee, if any.
fn ensure_valid_fee_cap(
max_fee: U256,
/// Get the effective gas price of a transaction as specfified in EIP-1559 with relevant
/// checks.
fn get_effective_gas_price(
max_fee_per_gas: Option<U256>,
max_priority_fee_per_gas: Option<U256>,
) -> EthResult<()> {
if let Some(max_priority) = max_priority_fee_per_gas {
if max_priority > max_fee {
// Fail early
return Err(
// `max_priority_fee_per_gas` is greater than the `max_fee_per_gas`
RpcInvalidTransactionError::TipAboveFeeCap.into(),
)
block_base_fee: U256,
) -> EthResult<U256> {
match max_fee_per_gas {
Some(max_fee) => {
if max_fee < block_base_fee {
// `base_fee_per_gas` is greater than the `max_fee_per_gas`
return Err(RpcInvalidTransactionError::FeeCapTooLow.into())
}
if max_fee < max_priority_fee_per_gas.unwrap_or(U256::ZERO) {
return Err(
// `max_priority_fee_per_gas` is greater than the `max_fee_per_gas`
RpcInvalidTransactionError::TipAboveFeeCap.into(),
)
}
Ok(min(
max_fee,
block_base_fee
.checked_add(max_priority_fee_per_gas.unwrap_or(U256::ZERO))
.ok_or_else(|| {
EthApiError::from(RpcInvalidTransactionError::TipVeryHigh)
})?,
))
}
None => Ok(block_base_fee
.checked_add(max_priority_fee_per_gas.unwrap_or(U256::ZERO))
.ok_or_else(|| EthApiError::from(RpcInvalidTransactionError::TipVeryHigh))?),
}
Ok(())
}
let has_blob_hashes =
@ -491,18 +507,26 @@ impl CallFees {
}
(None, max_fee_per_gas, max_priority_fee_per_gas, None) => {
// request for eip-1559 transaction
let max_fee = max_fee_per_gas.unwrap_or(block_base_fee);
ensure_valid_fee_cap(max_fee, max_priority_fee_per_gas)?;
let effective_gas_price = get_effective_gas_price(
max_fee_per_gas,
max_priority_fee_per_gas,
block_base_fee,
)?;
let max_fee_per_blob_gas = has_blob_hashes.then_some(block_blob_fee).flatten();
Ok(CallFees { gas_price: max_fee, max_priority_fee_per_gas, max_fee_per_blob_gas })
Ok(CallFees {
gas_price: effective_gas_price,
max_priority_fee_per_gas,
max_fee_per_blob_gas,
})
}
(None, max_fee_per_gas, max_priority_fee_per_gas, Some(max_fee_per_blob_gas)) => {
// request for eip-4844 transaction
let max_fee = max_fee_per_gas.unwrap_or(block_base_fee);
ensure_valid_fee_cap(max_fee, max_priority_fee_per_gas)?;
let effective_gas_price = get_effective_gas_price(
max_fee_per_gas,
max_priority_fee_per_gas,
block_base_fee,
)?;
// Ensure blob_hashes are present
if !has_blob_hashes {
// Blob transaction but no blob hashes
@ -510,7 +534,7 @@ impl CallFees {
}
Ok(CallFees {
gas_price: max_fee,
gas_price: effective_gas_price,
max_priority_fee_per_gas,
max_fee_per_blob_gas: Some(max_fee_per_blob_gas),
})
@ -629,6 +653,8 @@ where
#[cfg(test)]
mod tests {
use reth_primitives::constants::GWEI_TO_WEI;
use super::*;
#[test]
@ -660,4 +686,76 @@ mod tests {
assert!(gas_price.is_zero());
assert_eq!(max_fee_per_blob_gas, Some(U256::from(99)));
}
#[test]
fn test_eip_1559_fees() {
let CallFees { gas_price, .. } = CallFees::ensure_fees(
None,
Some(U256::from(25 * GWEI_TO_WEI)),
Some(U256::from(15 * GWEI_TO_WEI)),
U256::from(15 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
)
.unwrap();
assert_eq!(gas_price, U256::from(25 * GWEI_TO_WEI));
let CallFees { gas_price, .. } = CallFees::ensure_fees(
None,
Some(U256::from(25 * GWEI_TO_WEI)),
Some(U256::from(5 * GWEI_TO_WEI)),
U256::from(15 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
)
.unwrap();
assert_eq!(gas_price, U256::from(20 * GWEI_TO_WEI));
let CallFees { gas_price, .. } = CallFees::ensure_fees(
None,
Some(U256::from(30 * GWEI_TO_WEI)),
Some(U256::from(30 * GWEI_TO_WEI)),
U256::from(15 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
)
.unwrap();
assert_eq!(gas_price, U256::from(30 * GWEI_TO_WEI));
let call_fees = CallFees::ensure_fees(
None,
Some(U256::from(30 * GWEI_TO_WEI)),
Some(U256::from(31 * GWEI_TO_WEI)),
U256::from(15 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
);
assert!(call_fees.is_err());
let call_fees = CallFees::ensure_fees(
None,
Some(U256::from(5 * GWEI_TO_WEI)),
Some(U256::from(GWEI_TO_WEI)),
U256::from(15 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
);
assert!(call_fees.is_err());
let call_fees = CallFees::ensure_fees(
None,
Some(U256::MAX),
Some(U256::MAX),
U256::from(5 * GWEI_TO_WEI),
None,
None,
Some(U256::ZERO),
);
assert!(call_fees.is_err());
}
}