Skip to content

Commit cae0dad

Browse files
committed
refactor(anvil): use alloy envelope macro
- Updated TypedTransaction to use TransactionEnvelope - Removed unused/redundant code
1 parent f0e7140 commit cae0dad

File tree

5 files changed

+32
-262
lines changed

5 files changed

+32
-262
lines changed

crates/anvil/core/src/eth/transaction/mod.rs

Lines changed: 18 additions & 252 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Transaction related types
22
use alloy_consensus::{
3-
Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, Transaction, TxEip1559, TxEip2930,
4-
TxEnvelope, TxLegacy, TxReceipt, Typed2718,
3+
Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, Transaction, TransactionEnvelope,
4+
TxEip1559, TxEip2930, TxEnvelope, TxLegacy, TxReceipt, Typed2718,
55
constants::{
66
EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, EIP7702_TX_TYPE_ID,
77
LEGACY_TX_TYPE_ID,
@@ -14,7 +14,7 @@ use alloy_consensus::{
1414

1515
use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Encodable2718};
1616
use alloy_network::{AnyReceiptEnvelope, AnyRpcTransaction, AnyTransactionReceipt, AnyTxEnvelope};
17-
use alloy_primitives::{Address, B256, Bloom, Bytes, Signature, TxHash, TxKind, U64, U256};
17+
use alloy_primitives::{Address, B256, Bloom, Bytes, TxHash, TxKind, U64, U256};
1818
use alloy_rlp::{Decodable, Encodable, Header};
1919
use alloy_rpc_types::{
2020
AccessList, ConversionError, Transaction as RpcTransaction, TransactionReceipt,
@@ -581,19 +581,30 @@ impl PendingTransaction {
581581
}
582582

583583
/// Container type for signed, typed transactions.
584-
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
584+
#[derive(Clone, Debug, TransactionEnvelope)]
585+
#[envelope(
586+
alloy_consensus = alloy_consensus,
587+
tx_type_name = TxType,
588+
serde_cfg(all()),
589+
)]
585590
pub enum TypedTransaction {
586591
/// Legacy transaction type
592+
#[envelope(ty = 0)]
587593
Legacy(Signed<TxLegacy>),
588594
/// EIP-2930 transaction
595+
#[envelope(ty = 1)]
589596
EIP2930(Signed<TxEip2930>),
590597
/// EIP-1559 transaction
598+
#[envelope(ty = 2)]
591599
EIP1559(Signed<TxEip1559>),
592600
/// EIP-4844 transaction
601+
#[envelope(ty = 3)]
593602
EIP4844(Signed<TxEip4844Variant>),
594603
/// EIP-7702 transaction
604+
#[envelope(ty = 4)]
595605
EIP7702(Signed<TxEip7702>),
596606
/// op-stack deposit transaction
607+
#[envelope(ty = 126)]
597608
Deposit(TxDeposit),
598609
}
599610

@@ -647,73 +658,12 @@ impl TypedTransaction {
647658
}
648659
}
649660

650-
/// Returns true if the transaction uses dynamic fees: EIP1559, EIP4844 or EIP7702
651-
pub fn is_dynamic_fee(&self) -> bool {
652-
matches!(self, Self::EIP1559(_) | Self::EIP4844(_) | Self::EIP7702(_))
653-
}
654-
655-
pub fn gas_price(&self) -> u128 {
656-
match self {
657-
Self::Legacy(tx) => tx.tx().gas_price,
658-
Self::EIP2930(tx) => tx.tx().gas_price,
659-
Self::EIP1559(tx) => tx.tx().max_fee_per_gas,
660-
Self::EIP4844(tx) => tx.tx().tx().max_fee_per_gas,
661-
Self::EIP7702(tx) => tx.tx().max_fee_per_gas,
662-
Self::Deposit(_) => 0,
663-
}
664-
}
665-
666-
pub fn gas_limit(&self) -> u64 {
667-
match self {
668-
Self::Legacy(tx) => tx.tx().gas_limit,
669-
Self::EIP2930(tx) => tx.tx().gas_limit,
670-
Self::EIP1559(tx) => tx.tx().gas_limit,
671-
Self::EIP4844(tx) => tx.tx().tx().gas_limit,
672-
Self::EIP7702(tx) => tx.tx().gas_limit,
673-
Self::Deposit(tx) => tx.gas_limit,
674-
}
675-
}
676-
677-
pub fn value(&self) -> U256 {
678-
U256::from(match self {
679-
Self::Legacy(tx) => tx.tx().value,
680-
Self::EIP2930(tx) => tx.tx().value,
681-
Self::EIP1559(tx) => tx.tx().value,
682-
Self::EIP4844(tx) => tx.tx().tx().value,
683-
Self::EIP7702(tx) => tx.tx().value,
684-
Self::Deposit(tx) => tx.value,
685-
})
686-
}
687-
688-
pub fn data(&self) -> &Bytes {
689-
match self {
690-
Self::Legacy(tx) => &tx.tx().input,
691-
Self::EIP2930(tx) => &tx.tx().input,
692-
Self::EIP1559(tx) => &tx.tx().input,
693-
Self::EIP4844(tx) => &tx.tx().tx().input,
694-
Self::EIP7702(tx) => &tx.tx().input,
695-
Self::Deposit(tx) => &tx.input,
696-
}
697-
}
698-
699-
/// Returns the transaction type
700-
pub fn r#type(&self) -> Option<u8> {
701-
match self {
702-
Self::Legacy(_) => None,
703-
Self::EIP2930(_) => Some(1),
704-
Self::EIP1559(_) => Some(2),
705-
Self::EIP4844(_) => Some(3),
706-
Self::EIP7702(_) => Some(4),
707-
Self::Deposit(_) => Some(0x7E),
708-
}
709-
}
710-
711661
/// Max cost of the transaction
712662
/// It is the gas limit multiplied by the gas price,
713663
/// and if the transaction is EIP-4844, the result of (total blob gas cost * max fee per blob
714664
/// gas) is also added
715665
pub fn max_cost(&self) -> u128 {
716-
let mut max_cost = (self.gas_limit() as u128).saturating_mul(self.gas_price());
666+
let mut max_cost = (self.gas_limit() as u128).saturating_mul(self.gas_price().unwrap_or(0));
717667

718668
if self.is_eip4844() {
719669
max_cost = max_cost.saturating_add(
@@ -744,13 +694,6 @@ impl TypedTransaction {
744694
}
745695
}
746696

747-
pub fn max_fee_per_blob_gas(&self) -> Option<u128> {
748-
match self {
749-
Self::EIP4844(tx) => Some(tx.tx().tx().max_fee_per_blob_gas),
750-
_ => None,
751-
}
752-
}
753-
754697
/// Returns a helper type that contains commonly used values as fields
755698
pub fn essentials(&self) -> TransactionEssentials {
756699
match self {
@@ -841,60 +784,13 @@ impl TypedTransaction {
841784
}
842785
}
843786

844-
pub fn nonce(&self) -> u64 {
845-
match self {
846-
Self::Legacy(t) => t.tx().nonce,
847-
Self::EIP2930(t) => t.tx().nonce,
848-
Self::EIP1559(t) => t.tx().nonce,
849-
Self::EIP4844(t) => t.tx().tx().nonce,
850-
Self::EIP7702(t) => t.tx().nonce,
851-
Self::Deposit(_t) => 0,
852-
}
853-
}
854-
855-
pub fn chain_id(&self) -> Option<u64> {
856-
match self {
857-
Self::Legacy(t) => t.tx().chain_id,
858-
Self::EIP2930(t) => Some(t.tx().chain_id),
859-
Self::EIP1559(t) => Some(t.tx().chain_id),
860-
Self::EIP4844(t) => Some(t.tx().tx().chain_id),
861-
Self::EIP7702(t) => Some(t.tx().chain_id),
862-
Self::Deposit(t) => t.chain_id(),
863-
}
864-
}
865-
866787
pub fn as_legacy(&self) -> Option<&Signed<TxLegacy>> {
867788
match self {
868789
Self::Legacy(tx) => Some(tx),
869790
_ => None,
870791
}
871792
}
872793

873-
/// Returns true whether this tx is a legacy transaction
874-
pub fn is_legacy(&self) -> bool {
875-
matches!(self, Self::Legacy(_))
876-
}
877-
878-
/// Returns true whether this tx is a EIP1559 transaction
879-
pub fn is_eip1559(&self) -> bool {
880-
matches!(self, Self::EIP1559(_))
881-
}
882-
883-
/// Returns true whether this tx is a EIP2930 transaction
884-
pub fn is_eip2930(&self) -> bool {
885-
matches!(self, Self::EIP2930(_))
886-
}
887-
888-
/// Returns true whether this tx is a EIP4844 transaction
889-
pub fn is_eip4844(&self) -> bool {
890-
matches!(self, Self::EIP4844(_))
891-
}
892-
893-
/// Returns true whether this tx is a EIP7702 transaction
894-
pub fn is_eip7702(&self) -> bool {
895-
matches!(self, Self::EIP7702(_))
896-
}
897-
898794
/// Returns the hash of the transaction.
899795
///
900796
/// Note: If this transaction has the Impersonated signature then this returns a modified unique
@@ -931,136 +827,6 @@ impl TypedTransaction {
931827
Self::Deposit(tx) => Ok(tx.from),
932828
}
933829
}
934-
935-
/// Returns what kind of transaction this is
936-
pub fn kind(&self) -> TxKind {
937-
match self {
938-
Self::Legacy(tx) => tx.tx().to,
939-
Self::EIP2930(tx) => tx.tx().to,
940-
Self::EIP1559(tx) => tx.tx().to,
941-
Self::EIP4844(tx) => TxKind::Call(tx.tx().tx().to),
942-
Self::EIP7702(tx) => TxKind::Call(tx.tx().to),
943-
Self::Deposit(tx) => tx.to,
944-
}
945-
}
946-
947-
/// Returns the callee if this transaction is a call
948-
pub fn to(&self) -> Option<Address> {
949-
self.kind().to().copied()
950-
}
951-
952-
/// Returns the Signature of the transaction
953-
pub fn signature(&self) -> Signature {
954-
match self {
955-
Self::Legacy(tx) => *tx.signature(),
956-
Self::EIP2930(tx) => *tx.signature(),
957-
Self::EIP1559(tx) => *tx.signature(),
958-
Self::EIP4844(tx) => *tx.signature(),
959-
Self::EIP7702(tx) => *tx.signature(),
960-
Self::Deposit(_) => Signature::from_scalars_and_parity(
961-
B256::with_last_byte(1),
962-
B256::with_last_byte(1),
963-
false,
964-
),
965-
}
966-
}
967-
}
968-
969-
impl Encodable for TypedTransaction {
970-
fn encode(&self, out: &mut dyn bytes::BufMut) {
971-
if !self.is_legacy() {
972-
Header { list: false, payload_length: self.encode_2718_len() }.encode(out);
973-
}
974-
975-
self.encode_2718(out);
976-
}
977-
}
978-
979-
impl Decodable for TypedTransaction {
980-
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
981-
let mut h_decode_copy = *buf;
982-
let header = alloy_rlp::Header::decode(&mut h_decode_copy)?;
983-
984-
// Legacy TX
985-
if header.list {
986-
return Ok(TxEnvelope::decode(buf)?.into());
987-
}
988-
989-
// Check byte after header
990-
let ty = *h_decode_copy.first().ok_or(alloy_rlp::Error::Custom("empty slice"))?;
991-
992-
if ty != 0x7E {
993-
Ok(TxEnvelope::decode(buf)?.into())
994-
} else {
995-
Ok(Self::Deposit(TxDeposit::decode_2718(buf)?))
996-
}
997-
}
998-
}
999-
1000-
impl Typed2718 for TypedTransaction {
1001-
fn ty(&self) -> u8 {
1002-
self.r#type().unwrap_or(0)
1003-
}
1004-
}
1005-
1006-
impl Encodable2718 for TypedTransaction {
1007-
fn encode_2718_len(&self) -> usize {
1008-
match self {
1009-
Self::Legacy(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(),
1010-
Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(),
1011-
Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(),
1012-
Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(),
1013-
Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(),
1014-
Self::Deposit(tx) => 1 + tx.length(),
1015-
}
1016-
}
1017-
1018-
fn encode_2718(&self, out: &mut dyn BufMut) {
1019-
match self {
1020-
Self::Legacy(tx) => TxEnvelope::from(tx.clone()).encode_2718(out),
1021-
Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718(out),
1022-
Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718(out),
1023-
Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718(out),
1024-
Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718(out),
1025-
Self::Deposit(tx) => {
1026-
tx.encode_2718(out);
1027-
}
1028-
}
1029-
}
1030-
}
1031-
1032-
impl Decodable2718 for TypedTransaction {
1033-
fn typed_decode(ty: u8, buf: &mut &[u8]) -> Result<Self, Eip2718Error> {
1034-
if ty == 0x7E {
1035-
return Ok(Self::Deposit(TxDeposit::decode(buf)?));
1036-
}
1037-
match TxEnvelope::typed_decode(ty, buf)? {
1038-
TxEnvelope::Eip2930(tx) => Ok(Self::EIP2930(tx)),
1039-
TxEnvelope::Eip1559(tx) => Ok(Self::EIP1559(tx)),
1040-
TxEnvelope::Eip4844(tx) => Ok(Self::EIP4844(tx)),
1041-
TxEnvelope::Eip7702(tx) => Ok(Self::EIP7702(tx)),
1042-
_ => Err(Eip2718Error::RlpError(alloy_rlp::Error::Custom("unexpected tx type"))),
1043-
}
1044-
}
1045-
1046-
fn fallback_decode(buf: &mut &[u8]) -> Result<Self, Eip2718Error> {
1047-
match TxEnvelope::fallback_decode(buf)? {
1048-
TxEnvelope::Legacy(tx) => Ok(Self::Legacy(tx)),
1049-
_ => Err(Eip2718Error::RlpError(alloy_rlp::Error::Custom("unexpected tx type"))),
1050-
}
1051-
}
1052-
}
1053-
1054-
impl From<TxEnvelope> for TypedTransaction {
1055-
fn from(value: TxEnvelope) -> Self {
1056-
match value {
1057-
TxEnvelope::Legacy(tx) => Self::Legacy(tx),
1058-
TxEnvelope::Eip2930(tx) => Self::EIP2930(tx),
1059-
TxEnvelope::Eip1559(tx) => Self::EIP1559(tx),
1060-
TxEnvelope::Eip4844(tx) => Self::EIP4844(tx),
1061-
TxEnvelope::Eip7702(tx) => Self::EIP7702(tx),
1062-
}
1063-
}
1064830
}
1065831

1066832
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -1556,7 +1322,7 @@ pub fn convert_to_anvil_receipt(receipt: AnyTransactionReceipt) -> Option<Receip
15561322
#[cfg(test)]
15571323
mod tests {
15581324
use super::*;
1559-
use alloy_primitives::{Log, LogData, b256, hex};
1325+
use alloy_primitives::{Log, LogData, Signature, b256, hex};
15601326
use std::str::FromStr;
15611327

15621328
// <https://github.com/foundry-rs/foundry/issues/10852>
@@ -1634,7 +1400,7 @@ mod tests {
16341400
// https://sepolia.etherscan.io/getRawTx?tx=0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
16351401
let raw_tx = alloy_primitives::hex::decode("0x03f9011d83aa36a7820fa28477359400852e90edd0008252089411e9ca82a3a762b4b5bd264d4173a242e7a770648080c08504a817c800f8a5a0012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921aa00152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4a0013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7a001148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1a0011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e654901a0c8de4cced43169f9aa3d36506363b2d2c44f6c49fc1fd91ea114c86f3757077ea01e11fdd0d1934eda0492606ee0bb80a7bf8f35cc5f86ec60fe5031ba48bfd544").unwrap();
16361402
let res = TypedTransaction::decode(&mut raw_tx.as_slice()).unwrap();
1637-
assert_eq!(res.r#type(), Some(3));
1403+
assert!(res.is_type(3));
16381404

16391405
let tx = match res {
16401406
TypedTransaction::EIP4844(tx) => tx,

crates/anvil/src/eth/api.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::{
3030
mem::transaction_build,
3131
};
3232
use alloy_consensus::{
33-
Account, Blob,
33+
Account, Blob, Transaction,
3434
transaction::{Recovered, eip4844::TxEip4844Variant},
3535
};
3636
use alloy_dyn_abi::TypedData;
@@ -2783,7 +2783,7 @@ impl EthApi {
27832783
let gas_price = tx.gas_price();
27842784
let value = tx.value();
27852785
let gas = tx.gas_limit();
2786-
TxpoolInspectSummary { to, value, gas, gas_price }
2786+
TxpoolInspectSummary { to, value, gas, gas_price: gas_price.unwrap_or(0) }
27872787
}
27882788

27892789
// Note: naming differs geth vs anvil:

crates/anvil/src/eth/backend/executor.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::{
1515
mem::inspector::AnvilInspector,
1616
};
1717
use alloy_consensus::{
18-
Receipt, ReceiptWithBloom, constants::EMPTY_WITHDRAWALS, proofs::calculate_receipt_root,
18+
Receipt, ReceiptWithBloom, Transaction, constants::EMPTY_WITHDRAWALS,
19+
proofs::calculate_receipt_root,
1920
};
2021
use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, eip7840::BlobParams};
2122
use alloy_evm::{

0 commit comments

Comments
 (0)