mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Fix(rpc) Effective gas_price for simulations (#6722)
This commit is contained in:
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user