Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/evm/src/block/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl ReceiptBuilder for MorphReceiptBuilder {
MorphTxType::Eip1559 => MorphReceipt::Eip1559(MorphTransactionReceipt::new(inner)),
MorphTxType::Eip7702 => MorphReceipt::Eip7702(MorphTransactionReceipt::new(inner)),
MorphTxType::L1Msg => MorphReceipt::L1Msg(inner),
MorphTxType::AltFee => MorphReceipt::AltFee(MorphTransactionReceipt::new(inner)),
MorphTxType::Morph => MorphReceipt::Morph(MorphTransactionReceipt::new(inner)),
}
}
}
6 changes: 3 additions & 3 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
//! Morph L2 extends Ethereum's transaction types with:
//!
//! - [`TxL1Msg`]: L1 message transactions (type `0x7E`) - deposits from L1
//! - [`TxAltFee`]: Alternative fee transactions (type `0x7F`) - pay gas with ERC20 tokens
//! - [`TxMorph`]: Morph transactions (type `0x7F`) - pay gas with ERC20 tokens
//! - [`MorphTxEnvelope`]: Transaction envelope containing all supported transaction types
//!
//! # Receipt Types
//!
//! - [`MorphReceipt`]: Receipt enum for all transaction types
//! - [`MorphTransactionReceipt`]: Extended receipt with L1 fee and AltFee fields
//! - [`MorphTransactionReceipt`]: Extended receipt with L1 fee and Morph transaction fields
//!
//! # Block Types
//!
Expand Down Expand Up @@ -61,7 +61,7 @@ pub use receipt::{MorphReceipt, MorphReceiptWithBloom, MorphTransactionReceipt};

// Re-export transaction types
pub use transaction::{
ALT_FEE_TX_TYPE_ID, L1_TX_TYPE_ID, MorphTxEnvelope, MorphTxType, TxAltFee, TxAltFeeExt, TxL1Msg,
L1_TX_TYPE_ID, MORPH_TX_TYPE_ID, MorphTxEnvelope, MorphTxType, TxL1Msg, TxMorph, TxMorphExt,
};

/// A [`NodePrimitives`] implementation for Morph.
Expand Down
52 changes: 26 additions & 26 deletions crates/primitives/src/receipt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Morph receipt types.
//!
//! This module provides:
//! - [`MorphTransactionReceipt`]: Receipt with L1 fee and AltFee fields
//! - [`MorphTransactionReceipt`]: Receipt with L1 fee and Morph transaction fields
//! - [`MorphReceipt`]: Typed receipt enum for different transaction types

#[allow(clippy::module_inception)]
Expand All @@ -22,7 +22,7 @@ use reth_primitives_traits::InMemorySize;
///
/// This enum wraps different receipt types based on the transaction type.
/// For L1 messages, it uses a standard receipt without L1 fee.
/// For other transactions, it uses [`MorphTransactionReceipt`] with L1 fee and optional AltFee fields.
/// For other transactions, it uses [`MorphTransactionReceipt`] with L1 fee and optional Morph transaction fields.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MorphReceipt {
Expand All @@ -36,8 +36,8 @@ pub enum MorphReceipt {
Eip7702(MorphTransactionReceipt),
/// L1 message receipt (no L1 fee since it's pre-paid on L1)
L1Msg(Receipt),
/// AltFee receipt
AltFee(MorphTransactionReceipt),
/// Morph transaction receipt
Morph(MorphTransactionReceipt),
}

impl Default for MorphReceipt {
Expand All @@ -55,7 +55,7 @@ impl MorphReceipt {
Self::Eip1559(_) => MorphTxType::Eip1559,
Self::Eip7702(_) => MorphTxType::Eip7702,
Self::L1Msg(_) => MorphTxType::L1Msg,
Self::AltFee(_) => MorphTxType::AltFee,
Self::Morph(_) => MorphTxType::Morph,
}
}

Expand All @@ -66,7 +66,7 @@ impl MorphReceipt {
| Self::Eip2930(receipt)
| Self::Eip1559(receipt)
| Self::Eip7702(receipt)
| Self::AltFee(receipt) => &receipt.inner,
| Self::Morph(receipt) => &receipt.inner,
Self::L1Msg(receipt) => receipt,
}
}
Expand All @@ -78,7 +78,7 @@ impl MorphReceipt {
| Self::Eip2930(r)
| Self::Eip1559(r)
| Self::Eip7702(r)
| Self::AltFee(r) => r.l1_fee,
| Self::Morph(r) => r.l1_fee,
Self::L1Msg(_) => None,
}
}
Expand All @@ -95,7 +95,7 @@ impl MorphReceipt {
| Self::Eip2930(r)
| Self::Eip1559(r)
| Self::Eip7702(r)
| Self::AltFee(r) => r.rlp_encoded_fields_length_with_bloom(bloom),
| Self::Morph(r) => r.rlp_encoded_fields_length_with_bloom(bloom),
Self::L1Msg(r) => r.rlp_encoded_fields_length_with_bloom(bloom),
}
}
Expand All @@ -107,7 +107,7 @@ impl MorphReceipt {
| Self::Eip2930(r)
| Self::Eip1559(r)
| Self::Eip7702(r)
| Self::AltFee(r) => r.rlp_encode_fields_with_bloom(bloom, out),
| Self::Morph(r) => r.rlp_encode_fields_with_bloom(bloom, out),
Self::L1Msg(r) => r.rlp_encode_fields_with_bloom(bloom, out),
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ impl MorphReceipt {
| Self::Eip2930(r)
| Self::Eip1559(r)
| Self::Eip7702(r)
| Self::AltFee(r) => {
| Self::Morph(r) => {
r.inner.status.length()
+ r.inner.cumulative_gas_used.length()
+ r.inner.logs.length()
Expand All @@ -159,7 +159,7 @@ impl MorphReceipt {
| Self::Eip2930(r)
| Self::Eip1559(r)
| Self::Eip7702(r)
| Self::AltFee(r) => {
| Self::Morph(r) => {
r.inner.status.encode(out);
r.inner.cumulative_gas_used.encode(out);
r.inner.logs.encode(out);
Expand Down Expand Up @@ -206,7 +206,7 @@ impl MorphReceipt {
MorphTxType::Eip1559 => Ok(Self::Eip1559(MorphTransactionReceipt::new(inner))),
MorphTxType::Eip7702 => Ok(Self::Eip7702(MorphTransactionReceipt::new(inner))),
MorphTxType::L1Msg => Ok(Self::L1Msg(inner)),
MorphTxType::AltFee => Ok(Self::AltFee(MorphTransactionReceipt::new(inner))),
MorphTxType::Morph => Ok(Self::Morph(MorphTransactionReceipt::new(inner))),
}
}

Expand All @@ -228,7 +228,7 @@ impl MorphReceipt {
MorphTxType::Eip1559 => Self::Eip1559(MorphTransactionReceipt::new(inner)),
MorphTxType::Eip7702 => Self::Eip7702(MorphTransactionReceipt::new(inner)),
MorphTxType::L1Msg => Self::L1Msg(inner),
MorphTxType::AltFee => Self::AltFee(MorphTransactionReceipt::new(inner)),
MorphTxType::Morph => Self::Morph(MorphTransactionReceipt::new(inner)),
};

Ok(ReceiptWithBloom {
Expand Down Expand Up @@ -476,7 +476,7 @@ mod compact {
| MorphReceipt::Eip2930(r)
| MorphReceipt::Eip1559(r)
| MorphReceipt::Eip7702(r)
| MorphReceipt::AltFee(r) => (
| MorphReceipt::Morph(r) => (
r.l1_fee,
r.fee_token_id.map(u64::from),
r.fee_rate,
Expand Down Expand Up @@ -540,7 +540,7 @@ mod compact {
MorphTxType::Eip1559 => Self::Eip1559(morph_receipt),
MorphTxType::Eip7702 => Self::Eip7702(morph_receipt),
MorphTxType::L1Msg => unreachable!("L1Msg handled above"),
MorphTxType::AltFee => Self::AltFee(morph_receipt),
MorphTxType::Morph => Self::Morph(morph_receipt),
}
}
}
Expand Down Expand Up @@ -615,15 +615,15 @@ mod tests {
})
}

/// Creates an AltFee receipt for testing.
fn create_alt_fee_receipt() -> MorphReceipt {
/// Creates a Morph transaction receipt for testing.
fn create_morph_receipt() -> MorphReceipt {
let inner = Receipt {
status: false.into(),
cumulative_gas_used: 50000,
logs: vec![],
};

MorphReceipt::AltFee(MorphTransactionReceipt::with_alt_fee(
MorphReceipt::Morph(MorphTransactionReceipt::with_morph_tx(
inner,
U256::from(2000), // l1_fee
1, // fee_token_id
Expand All @@ -641,8 +641,8 @@ mod tests {
let l1_msg = MorphReceipt::L1Msg(Receipt::default());
assert_eq!(l1_msg.tx_type(), MorphTxType::L1Msg);

let alt_fee = MorphReceipt::AltFee(MorphTransactionReceipt::default());
assert_eq!(alt_fee.tx_type(), MorphTxType::AltFee);
let morph = MorphReceipt::Morph(MorphTransactionReceipt::default());
assert_eq!(morph.tx_type(), MorphTxType::Morph);
}

#[test]
Expand Down Expand Up @@ -762,23 +762,23 @@ mod tests {
assert!(decoded.is_l1_message());
}

/// Tests that EIP-2718 encoding and decoding roundtrips correctly for AltFee receipt.
/// Tests that EIP-2718 encoding and decoding roundtrips correctly for Morph receipt.
#[test]
fn test_alt_fee_receipt_encode_2718_roundtrip() {
let original = create_alt_fee_receipt();
fn test_morph_receipt_encode_2718_roundtrip() {
let original = create_morph_receipt();

// Encode
let mut encoded = Vec::new();
original.encode_2718(&mut encoded);

// Verify type byte
assert_eq!(encoded[0], MorphTxType::AltFee as u8);
assert_eq!(encoded[0], MorphTxType::Morph as u8);

// Decode
let decoded = MorphReceipt::decode_2718(&mut encoded.as_slice()).unwrap();

// Verify fields
assert_eq!(decoded.tx_type(), MorphTxType::AltFee);
assert_eq!(decoded.tx_type(), MorphTxType::Morph);
assert_eq!(decoded.status(), original.status());
assert_eq!(
decoded.cumulative_gas_used(),
Expand Down Expand Up @@ -887,7 +887,7 @@ mod tests {
(MorphTxType::Legacy, create_legacy_receipt()),
(MorphTxType::Eip1559, create_test_receipt()),
(MorphTxType::L1Msg, create_l1_msg_receipt()),
(MorphTxType::AltFee, create_alt_fee_receipt()),
(MorphTxType::Morph, create_morph_receipt()),
];

for (expected_type, original) in receipts {
Expand Down
42 changes: 21 additions & 21 deletions crates/primitives/src/receipt/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
//!
//! This module defines the Morph-specific receipt types that include:
//! - L1 data fee for rollup transactions
//! - AltFee fields for alternative fee token transactions
//! - Morph transaction fields for alternative fee token transactions

use alloy_consensus::{Eip658Value, Receipt, ReceiptWithBloom, TxReceipt};
use alloy_primitives::{Bloom, Log, U256};
use alloy_rlp::{BufMut, Decodable, Encodable, Header};

/// Morph transaction receipt with L1 fee and AltFee fields.
/// Morph transaction receipt with L1 fee and Morph transaction fields.
///
/// This receipt extends the standard Ethereum receipt with:
/// - `l1_fee`: The L1 data fee charged for posting transaction data to L1
/// - `fee_token_id`: The ERC20 token ID used for fee payment (AltFee)
/// - `fee_token_id`: The ERC20 token ID used for fee payment (TxMorph)
/// - `fee_rate`: The exchange rate for the fee token
/// - `token_scale`: The scale factor for the token
/// - `fee_limit`: The fee limit for AltFee transactions
/// - `fee_limit`: The fee limit for TxMorph
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
Expand All @@ -32,32 +32,32 @@ pub struct MorphTransactionReceipt<T = Log> {
)]
pub l1_fee: Option<U256>,

/// The ERC20 token ID used for fee payment (AltFee feature).
/// Only present for AltFee transactions.
/// The ERC20 token ID used for fee payment (TxMorph feature).
/// Only present for TxMorph.
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub fee_token_id: Option<u16>,

/// The exchange rate for the fee token.
/// Only present for AltFee transactions.
/// Only present for TxMorph.
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub fee_rate: Option<U256>,

/// The scale factor for the token.
/// Only present for AltFee transactions.
/// Only present for TxMorph.
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub token_scale: Option<U256>,

/// The fee limit for the AltFee transaction.
/// Only present for AltFee transactions.
/// The fee limit for the TxMorph.
/// Only present for TxMorph.
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
Expand Down Expand Up @@ -90,8 +90,8 @@ impl<T> MorphTransactionReceipt<T> {
}
}

/// Creates a new receipt with AltFee fields.
pub const fn with_alt_fee(
/// Creates a new receipt with TxMorph fields.
pub const fn with_morph_tx(
inner: Receipt<T>,
l1_fee: U256,
fee_token_id: u16,
Expand All @@ -109,8 +109,8 @@ impl<T> MorphTransactionReceipt<T> {
}
}

/// Returns true if this receipt is for an AltFee transaction.
pub const fn is_alt_fee(&self) -> bool {
/// Returns true if this receipt is for a TxMorph.
pub const fn is_morph_tx(&self) -> bool {
self.fee_token_id.is_some()
}

Expand All @@ -136,15 +136,15 @@ impl MorphTransactionReceipt {
impl<T: Encodable> MorphTransactionReceipt<T> {
/// Returns length of RLP-encoded receipt fields with the given [`Bloom`] without an RLP header.
///
/// Note: L1 fee and AltFee fields are NOT included in the RLP encoding for consensus,
/// Note: L1 fee and TxMorph fields are NOT included in the RLP encoding for consensus,
/// matching go-ethereum's behavior.
pub fn rlp_encoded_fields_length_with_bloom(&self, bloom: &Bloom) -> usize {
self.inner.rlp_encoded_fields_length_with_bloom(bloom)
}

/// RLP-encodes receipt fields with the given [`Bloom`] without an RLP header.
///
/// Note: L1 fee and AltFee fields are NOT included in the RLP encoding for consensus,
/// Note: L1 fee and TxMorph fields are NOT included in the RLP encoding for consensus,
/// matching go-ethereum's behavior.
pub fn rlp_encode_fields_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) {
self.inner.rlp_encode_fields_with_bloom(bloom, out);
Expand Down Expand Up @@ -251,7 +251,7 @@ mod tests {
assert_eq!(receipt.cumulative_gas_used(), 21000);
assert!(receipt.l1_fee.is_none());
assert!(receipt.fee_token_id.is_none());
assert!(!receipt.is_alt_fee());
assert!(!receipt.is_morph_tx());
}

#[test]
Expand All @@ -266,11 +266,11 @@ mod tests {

assert_eq!(receipt.l1_fee, Some(l1_fee));
assert_eq!(receipt.l1_fee_or_zero(), l1_fee);
assert!(!receipt.is_alt_fee());
assert!(!receipt.is_morph_tx());
}

#[test]
fn test_morph_receipt_with_alt_fee() {
fn test_morph_receipt_with_morph_tx() {
let inner: Receipt<Log> = Receipt {
status: true.into(),
cumulative_gas_used: 21000,
Expand All @@ -282,7 +282,7 @@ mod tests {
let token_scale = U256::from(18);
let fee_limit = U256::from(5000000);

let receipt = MorphTransactionReceipt::with_alt_fee(
let receipt = MorphTransactionReceipt::with_morph_tx(
inner,
l1_fee,
fee_token_id,
Expand All @@ -291,7 +291,7 @@ mod tests {
fee_limit,
);

assert!(receipt.is_alt_fee());
assert!(receipt.is_morph_tx());
assert_eq!(receipt.fee_token_id, Some(fee_token_id));
assert_eq!(receipt.fee_rate, Some(fee_rate));
assert_eq!(receipt.token_scale, Some(token_scale));
Expand Down
Loading