From 35e2421022ec541c1926481b21fb3aa157664056 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 5 May 2023 19:08:52 +0200 Subject: [PATCH] feat(rpc): set eip1559 gasPrice field (#2579) --- crates/primitives/src/transaction/mod.rs | 43 ++++++++++--------- .../src/tracing/builder/parity.rs | 2 +- crates/rpc/rpc-types/src/eth/block.rs | 1 + .../rpc-types/src/eth/transaction/common.rs | 2 + .../rpc/rpc-types/src/eth/transaction/mod.rs | 37 ++++++++++++---- crates/rpc/rpc/src/eth/api/transactions.rs | 27 ++++++++---- crates/rpc/rpc/src/trace.rs | 1 + 7 files changed, 74 insertions(+), 39 deletions(-) diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 0cf9997fdd..a043d887d9 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -363,26 +363,6 @@ impl Transaction { } } - // TODO: dedup with effective_tip_per_gas - /// Determine the effective gas limit for the given transaction and base fee. - /// If the base fee is `None`, the `max_priority_fee_per_gas`, or gas price for non-EIP1559 - /// transactions is returned. - /// - /// If the `max_fee_per_gas` is less than the base fee, `None` returned. - pub fn effective_gas_tip(&self, base_fee: Option) -> Option { - if let Some(base_fee) = base_fee { - let max_fee_per_gas = self.max_fee_per_gas(); - if max_fee_per_gas < base_fee as u128 { - None - } else { - let effective_max_fee = max_fee_per_gas - base_fee as u128; - Some(std::cmp::min(effective_max_fee, self.priority_fee_or_price())) - } - } else { - Some(self.priority_fee_or_price()) - } - } - /// Return the max priority fee per gas if the transaction is an EIP-1559 transaction, and /// otherwise return the gas price. /// @@ -413,7 +393,28 @@ impl Transaction { dynamic_tx.effective_gas_price(base_fee) } - /// Returns the effective miner gas tip cap (`gasTipCap`) for the given base fee. + // TODO: dedup with effective_tip_per_gas + /// Determine the effective gas limit for the given transaction and base fee. + /// If the base fee is `None`, the `max_priority_fee_per_gas`, or gas price for non-EIP1559 + /// transactions is returned. + /// + /// If the `max_fee_per_gas` is less than the base fee, `None` returned. + pub fn effective_gas_tip(&self, base_fee: Option) -> Option { + if let Some(base_fee) = base_fee { + let max_fee_per_gas = self.max_fee_per_gas(); + if max_fee_per_gas < base_fee as u128 { + None + } else { + let effective_max_fee = max_fee_per_gas - base_fee as u128; + Some(std::cmp::min(effective_max_fee, self.priority_fee_or_price())) + } + } else { + Some(self.priority_fee_or_price()) + } + } + + /// Returns the effective miner gas tip cap (`gasTipCap`) for the given base fee: + /// `min(maxFeePerGas - baseFee, maxPriorityFeePerGas)` /// /// Returns `None` if the basefee is higher than the [Transaction::max_fee_per_gas]. pub fn effective_tip_per_gas(&self, base_fee: u64) -> Option { diff --git a/crates/revm/revm-inspectors/src/tracing/builder/parity.rs b/crates/revm/revm-inspectors/src/tracing/builder/parity.rs index c17d49a415..13a50de5b7 100644 --- a/crates/revm/revm-inspectors/src/tracing/builder/parity.rs +++ b/crates/revm/revm-inspectors/src/tracing/builder/parity.rs @@ -64,7 +64,7 @@ impl ParityTraceBuilder { info: TransactionInfo, ) -> impl Iterator { self.into_transaction_traces_iter().map(move |trace| { - let TransactionInfo { hash, index, block_hash, block_number } = info; + let TransactionInfo { hash, index, block_hash, block_number, .. } = info; LocalizedTransactionTrace { trace, transaction_position: index, diff --git a/crates/rpc/rpc-types/src/eth/block.rs b/crates/rpc/rpc-types/src/eth/block.rs index c6f01a9e29..ff47937af4 100644 --- a/crates/rpc/rpc-types/src/eth/block.rs +++ b/crates/rpc/rpc-types/src/eth/block.rs @@ -144,6 +144,7 @@ impl Block { signed_tx, block_hash, block_number, + block.base_fee_per_gas, U256::from(idx), )) } diff --git a/crates/rpc/rpc-types/src/eth/transaction/common.rs b/crates/rpc/rpc-types/src/eth/transaction/common.rs index 5b9b0a25a1..839630593a 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/common.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/common.rs @@ -14,4 +14,6 @@ pub struct TransactionInfo { pub block_hash: Option, /// Number of the block. pub block_number: Option, + /// Base fee of the block. + pub base_fee: Option, } diff --git a/crates/rpc/rpc-types/src/eth/transaction/mod.rs b/crates/rpc/rpc-types/src/eth/transaction/mod.rs index a5cc79b233..10982e3cc5 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/mod.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/mod.rs @@ -80,18 +80,27 @@ impl Transaction { tx: TransactionSignedEcRecovered, block_hash: H256, block_number: BlockNumber, + base_fee: Option, tx_index: U256, ) -> Self { - let mut tx = Self::from_recovered(tx); - tx.block_hash = Some(block_hash); - tx.block_number = Some(U256::from(block_number)); - tx.transaction_index = Some(tx_index); - tx + Self::fill(tx, Some(block_hash), Some(block_number), base_fee, Some(tx_index)) } /// Create a new rpc transaction result for a _pending_ signed transaction, setting block /// environment related fields to `None`. pub fn from_recovered(tx: TransactionSignedEcRecovered) -> Self { + Self::fill(tx, None, None, None, None) + } + + /// Create a new rpc transaction result for a _pending_ signed transaction, setting block + /// environment related fields to `None`. + fn fill( + tx: TransactionSignedEcRecovered, + block_hash: Option, + block_number: Option, + base_fee: Option, + transaction_index: Option, + ) -> Self { let signer = tx.signer(); let signed_tx = tx.into_signed(); @@ -103,7 +112,17 @@ impl Transaction { let (gas_price, max_fee_per_gas) = match signed_tx.tx_type() { TxType::Legacy => (Some(U128::from(signed_tx.max_fee_per_gas())), None), TxType::EIP2930 => (None, Some(U128::from(signed_tx.max_fee_per_gas()))), - TxType::EIP1559 => (None, Some(U128::from(signed_tx.max_fee_per_gas()))), + TxType::EIP1559 => { + // the gas price field for EIP1559 is set to `min(tip, gasFeeCap - baseFee) + + // baseFee` + let gas_price = base_fee + .and_then(|base_fee| { + signed_tx.effective_tip_per_gas(base_fee).map(|tip| tip + base_fee as u128) + }) + .unwrap_or_else(|| signed_tx.max_fee_per_gas()); + + (Some(U128::from(gas_price)), Some(U128::from(signed_tx.max_fee_per_gas()))) + } }; let chain_id = signed_tx.chain_id().map(U64::from); @@ -154,9 +173,9 @@ impl Transaction { transaction_type: Some(U64::from(signed_tx.tx_type() as u8)), // These fields are set to None because they are not stored as part of the transaction - block_hash: None, - block_number: None, - transaction_index: None, + block_hash, + block_number: block_number.map(U256::from), + transaction_index, } } } diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 000cf83e67..1282d5d9ef 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -234,11 +234,12 @@ where let transaction = tx.into_ecrecovered().ok_or(EthApiError::InvalidTransactionSignature)?; - let tx = TransactionSource::Database { + let tx = TransactionSource::Block { transaction, index: meta.index, block_hash: meta.block_hash, block_number: meta.block_number, + base_fee: meta.base_fee, }; Ok(Some(tx)) } @@ -256,18 +257,20 @@ where tx @ TransactionSource::Pool(_) => { (tx, BlockId::Number(BlockNumberOrTag::Pending)) } - TransactionSource::Database { + TransactionSource::Block { transaction, index, block_hash, block_number, + base_fee, } => { let at = BlockId::Hash(block_hash.into()); - let tx = TransactionSource::Database { + let tx = TransactionSource::Block { transaction, index, block_hash, block_number, + base_fee, }; (tx, at) } @@ -548,6 +551,7 @@ where tx, block_hash, block.header.number, + block.header.base_fee_per_gas, index.into(), ))) } @@ -644,8 +648,10 @@ where pub enum TransactionSource { /// Transaction exists in the pool (Pending) Pool(TransactionSignedEcRecovered), - /// Transaction already executed - Database { + /// Transaction already included in a block + /// + /// This can be a historical block or a pending block (received from the CL) + Block { /// Transaction fetched via provider transaction: TransactionSignedEcRecovered, /// Index of the transaction in the block @@ -654,6 +660,8 @@ pub enum TransactionSource { block_hash: H256, /// Number of the block. block_number: u64, + /// base fee of the block. + base_fee: Option, }, } @@ -677,10 +685,11 @@ impl TransactionSource { index: None, block_hash: None, block_number: None, + base_fee: None, }, ) } - TransactionSource::Database { transaction, index, block_hash, block_number } => { + TransactionSource::Block { transaction, index, block_hash, block_number, base_fee } => { let hash = transaction.hash(); ( transaction, @@ -689,6 +698,7 @@ impl TransactionSource { index: Some(index), block_hash: Some(block_hash), block_number: Some(block_number), + base_fee, }, ) } @@ -700,7 +710,7 @@ impl From for TransactionSignedEcRecovered { fn from(value: TransactionSource) -> Self { match value { TransactionSource::Pool(tx) => tx, - TransactionSource::Database { transaction, .. } => transaction, + TransactionSource::Block { transaction, .. } => transaction, } } } @@ -709,11 +719,12 @@ impl From for Transaction { fn from(value: TransactionSource) -> Self { match value { TransactionSource::Pool(tx) => Transaction::from_recovered(tx), - TransactionSource::Database { transaction, index, block_hash, block_number } => { + TransactionSource::Block { transaction, index, block_hash, block_number, base_fee } => { Transaction::from_recovered_with_block_context( transaction, block_hash, block_number, + base_fee, U256::from(index), ) } diff --git a/crates/rpc/rpc/src/trace.rs b/crates/rpc/rpc/src/trace.rs index 1a4369f1de..24946baa5c 100644 --- a/crates/rpc/rpc/src/trace.rs +++ b/crates/rpc/rpc/src/trace.rs @@ -237,6 +237,7 @@ where index: Some(idx as u64), block_hash: Some(block_hash), block_number: Some(block_env.number.try_into().unwrap_or(u64::MAX)), + base_fee: Some(block_env.basefee.try_into().unwrap_or(u64::MAX)), }; let tx = tx_env_with_recovered(&tx);