feat: migrate to alloy TxEip1559 (#10262)

Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
This commit is contained in:
Aurélien
2024-08-31 19:36:28 +02:00
committed by GitHub
parent 17f6225fa5
commit 3a49a552c7
14 changed files with 149 additions and 299 deletions

View File

@ -283,7 +283,7 @@ mod tests {
nonce: 26u64,
max_priority_fee_per_gas: 1500000000,
max_fee_per_gas: 1500000013,
gas_limit: 21000u64,
gas_limit: 21000,
to: TxKind::Call(hex!("61815774383099e24810ab832a5b2a5425c154d5").into()),
value: U256::from(3000000000000000000u64),
input: Default::default(),
@ -422,7 +422,7 @@ mod tests {
nonce: 26u64,
max_priority_fee_per_gas: 1500000000,
max_fee_per_gas: 1500000013,
gas_limit: 21000u64,
gas_limit: 21000,
to: TxKind::Call(hex!("61815774383099e24810ab832a5b2a5425c154d5").into()),
value: U256::from(3000000000000000000u64),
input: Default::default(),

View File

@ -135,10 +135,7 @@ impl TryFrom<WithOtherFields<alloy_rpc_types::Transaction>> for Transaction {
max_fee_per_gas: tx
.max_fee_per_gas
.ok_or(ConversionError::MissingMaxFeePerGas)?,
gas_limit: tx
.gas
.try_into()
.map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?,
gas_limit: tx.gas,
to: tx.to.map_or(TxKind::Create, TxKind::Call),
value: tx.value,
access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?,

View File

@ -50,7 +50,7 @@ impl FillTxEnv for TransactionSigned {
tx_env.authorization_list = None;
}
Transaction::Eip1559(tx) => {
tx_env.gas_limit = tx.gas_limit;
tx_env.gas_limit = tx.gas_limit as u64;
tx_env.gas_price = U256::from(tx.max_fee_per_gas);
tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas));
tx_env.transact_to = tx.to;

View File

@ -1,245 +1,4 @@
use super::access_list::AccessList;
use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256};
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
use core::mem;
#[cfg(any(test, feature = "reth-codec"))]
use reth_codecs::Compact;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
/// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)).
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
pub struct TxEip1559 {
/// Added as EIP-155: Simple replay attack protection
pub chain_id: ChainId,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
pub nonce: u64,
/// A scalar value equal to the maximum
/// amount of gas that should be used in executing
/// this transaction. This is paid up-front, before any
/// computation is done and may not be increased
/// later; formally Tg.
pub gas_limit: u64,
/// A scalar value equal to the maximum
/// amount of gas that should be used in executing
/// this transaction. This is paid up-front, before any
/// computation is done and may not be increased
/// later; formally Tg.
///
/// As ethereum circulation is around 120mil eth as of 2022 that is around
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
/// 340282366920938463463374607431768211455
///
/// This is also known as `GasFeeCap`
pub max_fee_per_gas: u128,
/// Max Priority fee that transaction is paying
///
/// As ethereum circulation is around 120mil eth as of 2022 that is around
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
/// 340282366920938463463374607431768211455
///
/// This is also known as `GasTipCap`
pub max_priority_fee_per_gas: u128,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TxKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
pub value: U256,
/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
pub access_list: AccessList,
/// Input has two uses depending if the transaction `to` field is [`TxKind::Create`] or
/// [`TxKind::Call`].
///
/// Input as init code, or if `to` is [`TxKind::Create`]: An unlimited size byte array
/// specifying the EVM-code for the account initialisation procedure `CREATE`
///
/// Input as data, or if `to` is [`TxKind::Call`]: An unlimited size byte array specifying the
/// input data of the message call, formally Td.
pub input: Bytes,
}
impl TxEip1559 {
/// Returns the effective gas price for the given `base_fee`.
pub const fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
match base_fee {
None => self.max_fee_per_gas,
Some(base_fee) => {
// if the tip is greater than the max priority fee per gas, set it to the max
// priority fee per gas + base fee
let tip = self.max_fee_per_gas.saturating_sub(base_fee as u128);
if tip > self.max_priority_fee_per_gas {
self.max_priority_fee_per_gas + base_fee as u128
} else {
// otherwise return the max fee per gas
self.max_fee_per_gas
}
}
}
}
/// Decodes the inner [`TxEip1559`] fields from RLP bytes.
///
/// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following
/// RLP fields in the following order:
///
/// - `chain_id`
/// - `nonce`
/// - `max_priority_fee_per_gas`
/// - `max_fee_per_gas`
/// - `gas_limit`
/// - `to`
/// - `value`
/// - `data` (`input`)
/// - `access_list`
pub(crate) fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
Ok(Self {
chain_id: Decodable::decode(buf)?,
nonce: Decodable::decode(buf)?,
max_priority_fee_per_gas: Decodable::decode(buf)?,
max_fee_per_gas: Decodable::decode(buf)?,
gas_limit: Decodable::decode(buf)?,
to: Decodable::decode(buf)?,
value: Decodable::decode(buf)?,
input: Decodable::decode(buf)?,
access_list: Decodable::decode(buf)?,
})
}
/// Encodes only the transaction's fields into the desired buffer, without a RLP header.
pub(crate) fn fields_len(&self) -> usize {
self.chain_id.length() +
self.nonce.length() +
self.max_priority_fee_per_gas.length() +
self.max_fee_per_gas.length() +
self.gas_limit.length() +
self.to.length() +
self.value.length() +
self.input.0.length() +
self.access_list.length()
}
/// Encodes only the transaction's fields into the desired buffer, without a RLP header.
pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) {
self.chain_id.encode(out);
self.nonce.encode(out);
self.max_priority_fee_per_gas.encode(out);
self.max_fee_per_gas.encode(out);
self.gas_limit.encode(out);
self.to.encode(out);
self.value.encode(out);
self.input.0.encode(out);
self.access_list.encode(out);
}
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
/// hash that for eip2718 does not require rlp header
///
/// This encodes the transaction as:
/// `rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit to, value, input,
/// access_list, y_parity, r, s)`
pub(crate) fn encode_with_signature(
&self,
signature: &Signature,
out: &mut dyn bytes::BufMut,
with_header: bool,
) {
let payload_length = self.fields_len() + signature.payload_len();
if with_header {
Header {
list: false,
payload_length: 1 + length_of_length(payload_length) + payload_length,
}
.encode(out);
}
out.put_u8(self.tx_type() as u8);
let header = Header { list: true, payload_length };
header.encode(out);
self.encode_fields(out);
signature.encode(out);
}
/// Output the length of the RLP signed transaction encoding, _without_ a RLP string header.
pub(crate) fn payload_len_with_signature_without_header(&self, signature: &Signature) -> usize {
let payload_length = self.fields_len() + signature.payload_len();
// 'transaction type byte length' + 'header length' + 'payload length'
1 + length_of_length(payload_length) + payload_length
}
/// Output the length of the RLP signed transaction encoding. This encodes with a RLP header.
pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize {
let len = self.payload_len_with_signature_without_header(signature);
length_of_length(len) + len
}
/// Get transaction type
pub(crate) const fn tx_type(&self) -> TxType {
TxType::Eip1559
}
/// Calculates a heuristic for the in-memory size of the [`TxEip1559`] transaction.
#[inline]
pub fn size(&self) -> usize {
mem::size_of::<ChainId>() + // chain_id
mem::size_of::<u64>() + // nonce
mem::size_of::<u64>() + // gas_limit
mem::size_of::<u128>() + // max_fee_per_gas
mem::size_of::<u128>() + // max_priority_fee_per_gas
self.to.size() + // to
mem::size_of::<U256>() + // value
self.access_list.size() + // access_list
self.input.len() // input
}
/// Encodes the EIP-1559 transaction in RLP for signing.
///
/// This encodes the transaction as:
/// `tx_type || rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to,
/// value, input, access_list)`
///
/// Note that there is no rlp header before the transaction type byte.
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
out.put_u8(self.tx_type() as u8);
Header { list: true, payload_length: self.fields_len() }.encode(out);
self.encode_fields(out);
}
/// Outputs the length of the signature RLP encoding for the transaction.
pub(crate) fn payload_len_for_signature(&self) -> usize {
let payload_length = self.fields_len();
// 'transaction type byte length' + 'header length' + 'payload length'
1 + length_of_length(payload_length) + payload_length
}
/// Outputs the signature hash of the transaction by first encoding without a signature, then
/// hashing.
pub(crate) fn signature_hash(&self) -> B256 {
let mut buf = Vec::with_capacity(self.payload_len_for_signature());
self.encode_for_signing(&mut buf);
keccak256(&buf)
}
}
pub use alloy_consensus::TxEip1559;
#[cfg(test)]
mod tests {
use super::TxEip1559;

View File

@ -153,9 +153,15 @@ impl<'a> arbitrary::Arbitrary<'a> for Transaction {
TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?),
};
if let Self::Legacy(tx) = &mut tx {
tx.gas_limit = (tx.gas_limit as u64).into();
};
match &mut tx {
Self::Legacy(tx) => {
tx.gas_limit = (tx.gas_limit as u64).into();
}
Self::Eip1559(tx) => {
tx.gas_limit = (tx.gas_limit as u64).into();
}
_ => {}
}
Ok(tx)
}
@ -231,7 +237,7 @@ impl Transaction {
match self {
Self::Legacy(_) => TxType::Legacy,
Self::Eip2930(access_list_tx) => access_list_tx.tx_type(),
Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.tx_type(),
Self::Eip1559(_) => TxType::Eip1559,
Self::Eip4844(blob_tx) => blob_tx.tx_type(),
Self::Eip7702(set_code_tx) => set_code_tx.tx_type(),
#[cfg(feature = "optimism")]
@ -294,9 +300,9 @@ impl Transaction {
/// Get the gas limit of the transaction.
pub const fn gas_limit(&self) -> u64 {
match self {
Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64,
Self::Legacy(TxLegacy { gas_limit, .. }) |
Self::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit as u64,
Self::Eip2930(TxEip2930 { gas_limit, .. }) |
Self::Eip1559(TxEip1559 { gas_limit, .. }) |
Self::Eip4844(TxEip4844 { gas_limit, .. }) |
Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit,
#[cfg(feature = "optimism")]
@ -523,9 +529,11 @@ impl Transaction {
Self::Eip2930(access_list_tx) => {
access_list_tx.encode_with_signature(signature, out, with_header)
}
Self::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.encode_with_signature(signature, out, with_header)
}
Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encode_with_signature(
&signature.as_signature_with_boolean_parity(),
out,
with_header,
),
Self::Eip4844(blob_tx) => blob_tx.encode_with_signature(signature, out, with_header),
Self::Eip7702(set_code_tx) => {
set_code_tx.encode_with_signature(signature, out, with_header)
@ -540,7 +548,7 @@ impl Transaction {
match self {
Self::Legacy(tx) => tx.gas_limit = gas_limit.into(),
Self::Eip2930(tx) => tx.gas_limit = gas_limit,
Self::Eip1559(tx) => tx.gas_limit = gas_limit,
Self::Eip1559(tx) => tx.gas_limit = gas_limit.into(),
Self::Eip4844(tx) => tx.gas_limit = gas_limit,
Self::Eip7702(tx) => tx.gas_limit = gas_limit,
#[cfg(feature = "optimism")]
@ -1204,9 +1212,10 @@ impl TransactionSigned {
Transaction::Eip2930(access_list_tx) => {
access_list_tx.payload_len_with_signature(&self.signature)
}
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.payload_len_with_signature(&self.signature)
}
Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature(
&self.signature.as_signature_with_boolean_parity(),
true,
),
Transaction::Eip4844(blob_tx) => blob_tx.payload_len_with_signature(&self.signature),
Transaction::Eip7702(set_code_tx) => {
set_code_tx.payload_len_with_signature(&self.signature)
@ -1335,7 +1344,7 @@ impl TransactionSigned {
let transaction = match tx_type {
TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_inner(data)?),
TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_inner(data)?),
TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?),
TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?),
TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?),
#[cfg(feature = "optimism")]
@ -1410,9 +1419,10 @@ impl TransactionSigned {
Transaction::Eip2930(access_list_tx) => {
access_list_tx.payload_len_with_signature_without_header(&self.signature)
}
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.payload_len_with_signature_without_header(&self.signature)
}
Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature(
&self.signature.as_signature_with_boolean_parity(),
false,
),
Transaction::Eip4844(blob_tx) => {
blob_tx.payload_len_with_signature_without_header(&self.signature)
}

View File

@ -312,7 +312,10 @@ impl PooledTransactionsElement {
}
Self::Eip1559 { transaction, signature, .. } => {
// method computes the payload len without a RLP header
transaction.payload_len_with_signature_without_header(signature)
transaction.encoded_len_with_signature(
&signature.as_signature_with_boolean_parity(),
false,
)
}
Self::Eip7702 { transaction, signature, .. } => {
// method computes the payload len without a RLP header
@ -358,9 +361,11 @@ impl PooledTransactionsElement {
Self::Eip2930 { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out, false)
}
Self::Eip1559 { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out, false)
}
Self::Eip1559 { transaction, signature, .. } => transaction.encode_with_signature(
&signature.as_signature_with_boolean_parity(),
out,
false,
),
Self::Eip7702 { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out, false)
}
@ -494,7 +499,11 @@ impl Encodable for PooledTransactionsElement {
}
Self::Eip1559 { transaction, signature, .. } => {
// encodes with string header
transaction.encode_with_signature(signature, out, true)
transaction.encode_with_signature(
&signature.as_signature_with_boolean_parity(),
out,
true,
)
}
Self::Eip7702 { transaction, signature, .. } => {
// encodes with string header
@ -523,7 +532,8 @@ impl Encodable for PooledTransactionsElement {
}
Self::Eip1559 { transaction, signature, .. } => {
// method computes the payload len with a RLP header
transaction.payload_len_with_signature(signature)
transaction
.encoded_len_with_signature(&signature.as_signature_with_boolean_parity(), true)
}
Self::Eip7702 { transaction, signature, .. } => {
// method computes the payload len with a RLP header

View File

@ -188,6 +188,12 @@ impl Signature {
SignatureWithParity::new(self.r, self.s, self.legacy_parity(chain_id))
}
/// Returns a signature with a boolean parity flag. This is useful when we want to encode
/// the `v` value as 0 or 1.
pub(crate) const fn as_signature_with_boolean_parity(&self) -> SignatureWithParity {
SignatureWithParity::new(self.r, self.s, Parity::Parity(self.odd_y_parity))
}
/// Returns the signature for the optimism deposit transactions, which don't include a
/// signature.
#[cfg(feature = "optimism")]

View File

@ -16,7 +16,7 @@ reth-codecs-derive = { path = "./derive", default-features = false }
# eth
alloy-consensus = { workspace = true, optional = true }
alloy-eips = { workspace = true, optional = true }
alloy-eips = { workspace = true, optional = true, features = ["serde"] }
alloy-genesis = { workspace = true, optional = true }
alloy-primitives.workspace = true
alloy-trie = { workspace = true, optional = true }

View File

@ -0,0 +1,67 @@
use crate::Compact;
use alloy_consensus::TxEip1559 as AlloyTxEip1559;
use alloy_eips::eip2930::AccessList;
use alloy_primitives::{Bytes, ChainId, TxKind, U256};
use serde::{Deserialize, Serialize};
/// [EIP-1559 Transaction](https://eips.ethereum.org/EIPS/eip-1559)
///
/// This is a helper type to use derive on it instead of manually managing `bitfield`.
///
/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive
/// will automatically apply to this type.
///
/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::transaction::TxEip1559`]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Compact, Default, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[cfg_attr(test, crate::add_arbitrary_tests(compact))]
pub(crate) struct TxEip1559 {
chain_id: ChainId,
nonce: u64,
gas_limit: u64,
max_fee_per_gas: u128,
max_priority_fee_per_gas: u128,
to: TxKind,
value: U256,
access_list: AccessList,
input: Bytes,
}
impl Compact for AlloyTxEip1559 {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
let tx = TxEip1559 {
chain_id: self.chain_id,
nonce: self.nonce,
gas_limit: self.gas_limit as u64,
max_fee_per_gas: self.max_fee_per_gas,
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
to: self.to,
value: self.value,
access_list: self.access_list.clone(),
input: self.input.clone(),
};
tx.to_compact(buf)
}
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
let (tx, _) = TxEip1559::from_compact(buf, len);
let alloy_tx = Self {
chain_id: tx.chain_id,
nonce: tx.nonce,
gas_limit: tx.gas_limit.into(),
max_fee_per_gas: tx.max_fee_per_gas,
max_priority_fee_per_gas: tx.max_priority_fee_per_gas,
to: tx.to,
value: tx.value,
access_list: tx.access_list,
input: tx.input,
};
(alloy_tx, buf)
}
}

View File

@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Default, Compact, Serialize, Deserialize)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[cfg_attr(test, crate::add_arbitrary_tests(compact))]
struct TxLegacy {
pub(crate) struct TxLegacy {
/// Added as EIP-155: Simple replay attack protection
chain_id: Option<ChainId>,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
@ -67,7 +67,7 @@ impl Compact for AlloyTxLegacy {
chain_id: tx.chain_id,
nonce: tx.nonce,
gas_price: tx.gas_price,
gas_limit: tx.gas_limit as u128,
gas_limit: tx.gas_limit.into(),
to: tx.to,
value: tx.value,
input: tx.input,
@ -76,19 +76,3 @@ impl Compact for AlloyTxLegacy {
(alloy_tx, buf)
}
}
#[cfg(test)]
mod tests {
use crate::alloy::transaction::TxLegacy;
// each value in the database has an extra field named flags that encodes metadata about other
// fields in the value, e.g. offset and length.
//
// this check is to ensure we do not inadvertently add too many fields to a struct which would
// expand the flags field and break backwards compatibility
#[test]
fn test_ensure_backwards_compatibility() {
assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3);
}
}

View File

@ -0,0 +1,20 @@
mod eip1559;
mod legacy;
#[cfg(test)]
mod tests {
// each value in the database has an extra field named flags that encodes metadata about other
// fields in the value, e.g. offset and length.
//
// this check is to ensure we do not inadvertently add too many fields to a struct which would
// expand the flags field and break backwards compatibility
use super::{eip1559::TxEip1559, legacy::TxLegacy};
#[test]
fn test_ensure_backwards_compatibility() {
assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3);
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
}
}

View File

@ -302,8 +302,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion));
mod tests {
use super::*;
use reth_primitives::{
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, TxEip4844,
Withdrawals,
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip2930, TxEip4844, Withdrawals,
};
use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
use reth_stages_types::{
@ -343,7 +342,6 @@ mod tests {
assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0);
assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);
@ -375,7 +373,6 @@ mod tests {
assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0);
assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);

View File

@ -160,7 +160,7 @@ impl TransactionBuilder {
TxEip1559 {
chain_id: self.chain_id,
nonce: self.nonce,
gas_limit: self.gas_limit,
gas_limit: self.gas_limit.into(),
max_fee_per_gas: self.max_fee_per_gas,
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
to: self.to,

View File

@ -843,7 +843,7 @@ impl TryFrom<TransactionSignedEcRecovered> for MockTransaction {
nonce,
max_fee_per_gas,
max_priority_fee_per_gas,
gas_limit,
gas_limit: gas_limit as u64,
to,
value,
input,
@ -966,7 +966,7 @@ impl From<MockTransaction> for Transaction {
} => Self::Eip1559(TxEip1559 {
chain_id,
nonce,
gas_limit,
gas_limit: gas_limit.into(),
max_fee_per_gas,
max_priority_fee_per_gas,
to,
@ -1077,7 +1077,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction {
nonce: *nonce,
max_fee_per_gas: *max_fee_per_gas,
max_priority_fee_per_gas: *max_priority_fee_per_gas,
gas_limit: *gas_limit,
gas_limit: *gas_limit as u64,
to: *to,
value: *value,
input: input.clone(),