diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index b8aeb7631..e3d546862 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -15,10 +15,11 @@ exclude.workspace = true workspace = true [dependencies] -alloy-primitives = { workspace = true, features = ["rlp"] } -alloy-consensus.workspace = true +# Alloy alloy-rlp.workspace = true alloy-eips.workspace = true +alloy-consensus.workspace = true +alloy-primitives = { workspace = true, features = ["rlp"] } # arbitrary arbitrary = { workspace = true, features = ["derive"], optional = true } diff --git a/crates/consensus/src/lib.rs b/crates/consensus/src/lib.rs index c56d37dd9..99f03fdc9 100644 --- a/crates/consensus/src/lib.rs +++ b/crates/consensus/src/lib.rs @@ -14,8 +14,8 @@ pub use receipt::{OpDepositReceipt, OpDepositReceiptWithBloom, OpReceiptEnvelope mod transaction; pub use transaction::{ - DepositSourceDomain, DepositSourceDomainIdentifier, L1InfoDepositSource, OpTxEnvelope, - OpTxType, OpTypedTransaction, TxDeposit, UpgradeDepositSource, UserDepositSource, + DepositSourceDomain, DepositSourceDomainIdentifier, DepositTransaction, L1InfoDepositSource, + OpTxEnvelope, OpTxType, OpTypedTransaction, TxDeposit, UpgradeDepositSource, UserDepositSource, DEPOSIT_TX_TYPE_ID, }; @@ -23,10 +23,6 @@ pub mod hardforks; pub use hardforks::Hardforks; mod block; -mod traits; - -pub use traits::DepositTransaction; - pub use block::OpBlock; /// Bincode-compatible serde implementations for consensus types. diff --git a/crates/consensus/src/receipt/envelope.rs b/crates/consensus/src/receipt/envelope.rs index fdbd2a789..659a82840 100644 --- a/crates/consensus/src/receipt/envelope.rs +++ b/crates/consensus/src/receipt/envelope.rs @@ -1,3 +1,5 @@ +//! Receipt envelope types for Optimism. + use crate::{OpDepositReceipt, OpDepositReceiptWithBloom, OpTxType}; use alloy_consensus::{Eip658Value, Receipt, ReceiptWithBloom, TxReceipt}; use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718}; @@ -262,3 +264,47 @@ where } } } + +#[cfg(test)] +mod tests { + use super::*; + use alloy_consensus::{Receipt, ReceiptWithBloom}; + use alloy_eips::eip2718::Encodable2718; + use alloy_primitives::{address, b256, bytes, hex, Log, LogData}; + use alloy_rlp::Encodable; + + #[cfg(not(feature = "std"))] + use alloc::{vec, vec::Vec}; + + // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 + #[test] + fn encode_legacy_receipt() { + let expected = hex!("f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); + + let mut data = vec![]; + let receipt = + OpReceiptEnvelope::Legacy(ReceiptWithBloom { + receipt: Receipt { + status: false.into(), + cumulative_gas_used: 0x1u128, + logs: vec![Log { + address: address!("0000000000000000000000000000000000000011"), + data: LogData::new_unchecked( + vec![ + b256!("000000000000000000000000000000000000000000000000000000000000dead"), + b256!("000000000000000000000000000000000000000000000000000000000000beef"), + ], + bytes!("0100ff"), + ), + }], + }, + logs_bloom: [0; 256].into(), + }); + + receipt.network_encode(&mut data); + + // check that the rlp length equals the length of the expected rlp + assert_eq!(receipt.length(), expected.len()); + assert_eq!(data, expected); + } +} diff --git a/crates/consensus/src/receipt/mod.rs b/crates/consensus/src/receipt/mod.rs index e58c5bdf3..a259ee52c 100644 --- a/crates/consensus/src/receipt/mod.rs +++ b/crates/consensus/src/receipt/mod.rs @@ -1,3 +1,5 @@ +//! Receipt types for Optimism. + use alloy_consensus::TxReceipt; mod envelope; @@ -14,166 +16,3 @@ pub trait OpTxReceipt: TxReceipt { /// Returns the deposit receipt version of the transaction. fn deposit_receipt_version(&self) -> Option; } - -#[cfg(test)] -mod tests { - use super::*; - use alloy_consensus::{Receipt, ReceiptWithBloom}; - use alloy_eips::eip2718::Encodable2718; - use alloy_primitives::{address, b256, bytes, hex, Bytes, Log, LogData}; - use alloy_rlp::{Decodable, Encodable}; - - #[cfg(not(feature = "std"))] - use alloc::{vec, vec::Vec}; - - // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 - #[test] - fn encode_legacy_receipt() { - let expected = hex!("f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); - - let mut data = vec![]; - let receipt = - OpReceiptEnvelope::Legacy(ReceiptWithBloom { - receipt: Receipt { - status: false.into(), - cumulative_gas_used: 0x1u128, - logs: vec![Log { - address: address!("0000000000000000000000000000000000000011"), - data: LogData::new_unchecked( - vec![ - b256!("000000000000000000000000000000000000000000000000000000000000dead"), - b256!("000000000000000000000000000000000000000000000000000000000000beef"), - ], - bytes!("0100ff"), - ), - }], - }, - logs_bloom: [0; 256].into(), - }); - - receipt.network_encode(&mut data); - - // check that the rlp length equals the length of the expected rlp - assert_eq!(receipt.length(), expected.len()); - assert_eq!(data, expected); - } - - // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 - #[test] - fn decode_legacy_receipt() { - let data = hex!("f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); - - // EIP658Receipt - let expected = - OpDepositReceiptWithBloom { - receipt: OpDepositReceipt { - inner: Receipt { - status: false.into(), - cumulative_gas_used: 0x1u128, - logs: vec![Log { - address: address!("0000000000000000000000000000000000000011"), - data: LogData::new_unchecked( - vec![ - b256!("000000000000000000000000000000000000000000000000000000000000dead"), - b256!("000000000000000000000000000000000000000000000000000000000000beef"), - ], - bytes!("0100ff"), - ), - }], - }, - deposit_nonce: None, - deposit_receipt_version: None, - }, - logs_bloom: [0; 256].into(), - }; - - let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); - assert_eq!(receipt, expected); - } - - #[test] - fn gigantic_receipt() { - let receipt = OpDepositReceipt { - inner: Receipt { - cumulative_gas_used: 16747627, - status: true.into(), - logs: vec![ - Log { - address: address!("4bf56695415f725e43c3e04354b604bcfb6dfb6e"), - data: LogData::new_unchecked( - vec![b256!( - "c69dc3d7ebff79e41f525be431d5cd3cc08f80eaf0f7819054a726eeb7086eb9" - )], - Bytes::from(vec![1; 0xffffff]), - ), - }, - Log { - address: address!("faca325c86bf9c2d5b413cd7b90b209be92229c2"), - data: LogData::new_unchecked( - vec![b256!( - "8cca58667b1e9ffa004720ac99a3d61a138181963b294d270d91c53d36402ae2" - )], - Bytes::from(vec![1; 0xffffff]), - ), - }, - ], - }, - deposit_nonce: None, - deposit_receipt_version: None, - } - .with_bloom(); - - let mut data = vec![]; - - receipt.encode(&mut data); - let decoded = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); - - // receipt.clone().to_compact(&mut data); - // let (decoded, _) = Receipt::from_compact(&data[..], data.len()); - assert_eq!(decoded, receipt); - } - - #[test] - fn regolith_receipt_roundtrip() { - let data = hex!("f9010c0182b741b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0833d3bbf"); - - // Deposit Receipt (post-regolith) - let expected = OpDepositReceiptWithBloom { - receipt: OpDepositReceipt { - inner: Receipt { cumulative_gas_used: 46913, logs: vec![], status: true.into() }, - deposit_nonce: Some(4012991), - deposit_receipt_version: None, - }, - logs_bloom: [0; 256].into(), - }; - - let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); - assert_eq!(receipt, expected); - - let mut buf = Vec::new(); - receipt.encode(&mut buf); - assert_eq!(buf, &data[..]); - } - - #[test] - fn post_canyon_receipt_roundtrip() { - let data = hex!("f9010d0182b741b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0833d3bbf01"); - - // Deposit Receipt (post-regolith) - let expected = OpDepositReceiptWithBloom { - receipt: OpDepositReceipt { - inner: Receipt { cumulative_gas_used: 46913, logs: vec![], status: true.into() }, - deposit_nonce: Some(4012991), - deposit_receipt_version: Some(1), - }, - logs_bloom: [0; 256].into(), - }; - - let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); - assert_eq!(receipt, expected); - - let mut buf = Vec::new(); - expected.encode(&mut buf); - assert_eq!(buf, &data[..]); - } -} diff --git a/crates/consensus/src/receipt/receipts.rs b/crates/consensus/src/receipt/receipts.rs index fa9e0ac62..82530bb00 100644 --- a/crates/consensus/src/receipt/receipts.rs +++ b/crates/consensus/src/receipt/receipts.rs @@ -1,3 +1,5 @@ +//! Transaction receipt types for Optimism. + use super::OpTxReceipt; use alloy_consensus::{Eip658Value, Receipt, TxReceipt}; use alloy_primitives::{Bloom, Log}; @@ -293,3 +295,133 @@ where Ok(Self { receipt: OpDepositReceipt::::arbitrary(u)?, logs_bloom: Bloom::arbitrary(u)? }) } } + +#[cfg(test)] +mod tests { + use super::*; + use alloy_consensus::Receipt; + use alloy_primitives::{address, b256, bytes, hex, Bytes, Log, LogData}; + use alloy_rlp::{Decodable, Encodable}; + + #[cfg(not(feature = "std"))] + use alloc::{vec, vec::Vec}; + + // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 + #[test] + fn decode_legacy_receipt() { + let data = hex!("f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); + + // EIP658Receipt + let expected = + OpDepositReceiptWithBloom { + receipt: OpDepositReceipt { + inner: Receipt { + status: false.into(), + cumulative_gas_used: 0x1u128, + logs: vec![Log { + address: address!("0000000000000000000000000000000000000011"), + data: LogData::new_unchecked( + vec![ + b256!("000000000000000000000000000000000000000000000000000000000000dead"), + b256!("000000000000000000000000000000000000000000000000000000000000beef"), + ], + bytes!("0100ff"), + ), + }], + }, + deposit_nonce: None, + deposit_receipt_version: None, + }, + logs_bloom: [0; 256].into(), + }; + + let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); + assert_eq!(receipt, expected); + } + + #[test] + fn gigantic_receipt() { + let receipt = OpDepositReceipt { + inner: Receipt { + cumulative_gas_used: 16747627, + status: true.into(), + logs: vec![ + Log { + address: address!("4bf56695415f725e43c3e04354b604bcfb6dfb6e"), + data: LogData::new_unchecked( + vec![b256!( + "c69dc3d7ebff79e41f525be431d5cd3cc08f80eaf0f7819054a726eeb7086eb9" + )], + Bytes::from(vec![1; 0xffffff]), + ), + }, + Log { + address: address!("faca325c86bf9c2d5b413cd7b90b209be92229c2"), + data: LogData::new_unchecked( + vec![b256!( + "8cca58667b1e9ffa004720ac99a3d61a138181963b294d270d91c53d36402ae2" + )], + Bytes::from(vec![1; 0xffffff]), + ), + }, + ], + }, + deposit_nonce: None, + deposit_receipt_version: None, + } + .with_bloom(); + + let mut data = vec![]; + + receipt.encode(&mut data); + let decoded = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); + + // receipt.clone().to_compact(&mut data); + // let (decoded, _) = Receipt::from_compact(&data[..], data.len()); + assert_eq!(decoded, receipt); + } + + #[test] + fn regolith_receipt_roundtrip() { + let data = hex!("f9010c0182b741b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0833d3bbf"); + + // Deposit Receipt (post-regolith) + let expected = OpDepositReceiptWithBloom { + receipt: OpDepositReceipt { + inner: Receipt { cumulative_gas_used: 46913, logs: vec![], status: true.into() }, + deposit_nonce: Some(4012991), + deposit_receipt_version: None, + }, + logs_bloom: [0; 256].into(), + }; + + let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); + assert_eq!(receipt, expected); + + let mut buf = Vec::new(); + receipt.encode(&mut buf); + assert_eq!(buf, &data[..]); + } + + #[test] + fn post_canyon_receipt_roundtrip() { + let data = hex!("f9010d0182b741b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0833d3bbf01"); + + // Deposit Receipt (post-regolith) + let expected = OpDepositReceiptWithBloom { + receipt: OpDepositReceipt { + inner: Receipt { cumulative_gas_used: 46913, logs: vec![], status: true.into() }, + deposit_nonce: Some(4012991), + deposit_receipt_version: Some(1), + }, + logs_bloom: [0; 256].into(), + }; + + let receipt = OpDepositReceiptWithBloom::decode(&mut &data[..]).unwrap(); + assert_eq!(receipt, expected); + + let mut buf = Vec::new(); + expected.encode(&mut buf); + assert_eq!(buf, &data[..]); + } +} diff --git a/crates/consensus/src/traits.rs b/crates/consensus/src/traits.rs deleted file mode 100644 index 82e3d78ae..000000000 --- a/crates/consensus/src/traits.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::TxDeposit; -use alloy_primitives::B256; - -/// A trait representing a deposit transaction with specific attributes. -pub trait DepositTransaction { - /// Returns the hash that uniquely identifies the source of the deposit. - /// - /// # Returns - /// An `Option` containing the source hash if available. - fn source_hash(&self) -> Option; - - /// Returns the optional mint value of the deposit transaction. - /// - /// # Returns - /// An `Option` representing the ETH value to mint on L2, if any. - fn mint(&self) -> Option; - - /// Indicates whether the transaction is exempt from the L2 gas limit. - /// - /// # Returns - /// A `bool` indicating if the transaction is a system transaction. - fn is_system_transaction(&self) -> bool; - - /// Checks if the transaction is a deposit transaction. - /// - /// # Returns - /// A `bool` that is always `true` for deposit transactions. - fn is_deposit(&self) -> bool; -} - -impl DepositTransaction for TxDeposit { - fn source_hash(&self) -> Option { - Some(self.source_hash) - } - - fn mint(&self) -> Option { - self.mint - } - - fn is_system_transaction(&self) -> bool { - self.is_system_transaction - } - - fn is_deposit(&self) -> bool { - true - } -} - -#[cfg(test)] -mod tests { - use crate::{traits::DepositTransaction, TxDeposit}; - use alloy_consensus::Transaction; - use alloy_primitives::{Address, Bytes, TxKind, B256, U256}; - - #[test] - fn test_deposit_transaction_trait() { - let tx = TxDeposit { - source_hash: B256::with_last_byte(42), - from: Address::default(), - to: TxKind::default(), - mint: Some(100), - value: U256::from(1000), - gas_limit: 50000, - is_system_transaction: true, - input: Bytes::default(), - }; - - assert_eq!(tx.source_hash(), Some(B256::with_last_byte(42))); - assert_eq!(tx.mint(), Some(100)); - assert!(tx.is_system_transaction()); - assert!(tx.is_deposit()); - } - - #[test] - fn test_deposit_transaction_without_mint() { - let tx = TxDeposit { - source_hash: B256::default(), - from: Address::default(), - to: TxKind::default(), - mint: None, - value: U256::default(), - gas_limit: 50000, - is_system_transaction: false, - input: Bytes::default(), - }; - - assert_eq!(tx.source_hash(), Some(B256::default())); - assert_eq!(tx.mint(), None); - assert!(!tx.is_system_transaction()); - assert!(tx.is_deposit()); - } - - #[test] - fn test_deposit_transaction_to_contract() { - let contract_address = Address::with_last_byte(0xFF); - let tx = TxDeposit { - source_hash: B256::default(), - from: Address::default(), - to: TxKind::Call(contract_address), - mint: Some(200), - value: U256::from(500), - gas_limit: 100000, - is_system_transaction: false, - input: Bytes::from_static(&[1, 2, 3]), - }; - - assert_eq!(tx.source_hash(), Some(B256::default())); - assert_eq!(tx.mint(), Some(200)); - assert!(!tx.is_system_transaction()); - assert!(tx.is_deposit()); - assert_eq!(tx.kind(), TxKind::Call(contract_address)); - } -} diff --git a/crates/consensus/src/transaction/deposit.rs b/crates/consensus/src/transaction/deposit.rs index fd3015c66..ceb760c81 100644 --- a/crates/consensus/src/transaction/deposit.rs +++ b/crates/consensus/src/transaction/deposit.rs @@ -1,4 +1,7 @@ +//! Deposit Transaction type. + use super::OpTxType; +use crate::DepositTransaction; use alloy_consensus::Transaction; use alloy_eips::eip2930::AccessList; use alloy_primitives::{Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; @@ -37,6 +40,24 @@ pub struct TxDeposit { pub input: Bytes, } +impl DepositTransaction for TxDeposit { + fn source_hash(&self) -> Option { + Some(self.source_hash) + } + + fn mint(&self) -> Option { + self.mint + } + + fn is_system_transaction(&self) -> bool { + self.is_system_transaction + } + + fn is_deposit(&self) -> bool { + true + } +} + impl TxDeposit { /// Decodes the inner [TxDeposit] fields from RLP bytes. /// @@ -250,10 +271,68 @@ impl Decodable for TxDeposit { #[cfg(test)] mod tests { use super::*; - //use crate::TxEnvelope; use alloy_primitives::hex; use alloy_rlp::BytesMut; + #[test] + fn test_deposit_transaction_trait() { + let tx = TxDeposit { + source_hash: B256::with_last_byte(42), + from: Address::default(), + to: TxKind::default(), + mint: Some(100), + value: U256::from(1000), + gas_limit: 50000, + is_system_transaction: true, + input: Bytes::default(), + }; + + assert_eq!(tx.source_hash(), Some(B256::with_last_byte(42))); + assert_eq!(tx.mint(), Some(100)); + assert!(tx.is_system_transaction()); + assert!(tx.is_deposit()); + } + + #[test] + fn test_deposit_transaction_without_mint() { + let tx = TxDeposit { + source_hash: B256::default(), + from: Address::default(), + to: TxKind::default(), + mint: None, + value: U256::default(), + gas_limit: 50000, + is_system_transaction: false, + input: Bytes::default(), + }; + + assert_eq!(tx.source_hash(), Some(B256::default())); + assert_eq!(tx.mint(), None); + assert!(!tx.is_system_transaction()); + assert!(tx.is_deposit()); + } + + #[test] + fn test_deposit_transaction_to_contract() { + let contract_address = Address::with_last_byte(0xFF); + let tx = TxDeposit { + source_hash: B256::default(), + from: Address::default(), + to: TxKind::Call(contract_address), + mint: Some(200), + value: U256::from(500), + gas_limit: 100000, + is_system_transaction: false, + input: Bytes::from_static(&[1, 2, 3]), + }; + + assert_eq!(tx.source_hash(), Some(B256::default())); + assert_eq!(tx.mint(), Some(200)); + assert!(!tx.is_system_transaction()); + assert!(tx.is_deposit()); + assert_eq!(tx.kind(), TxKind::Call(contract_address)); + } + #[test] fn test_rlp_roundtrip() { let bytes = Bytes::from_static(&hex!("7ef9015aa044bae9d41b8380d781187b426c6fe43df5fb2fb57bd4466ef6a701e1f01e015694deaddeaddeaddeaddeaddeaddeaddeaddead000194420000000000000000000000000000000000001580808408f0d18001b90104015d8eb900000000000000000000000000000000000000000000000000000000008057650000000000000000000000000000000000000000000000000000000063d96d10000000000000000000000000000000000000000000000000000000000009f35273d89754a1e0387b89520d989d3be9c37c1f32495a88faf1ea05c61121ab0d1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000002d679b567db6187c0c8323fa982cfb88b74dbcc7000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240")); diff --git a/crates/consensus/src/transaction/mod.rs b/crates/consensus/src/transaction/mod.rs index 2b3816f44..4fce2ecb3 100644 --- a/crates/consensus/src/transaction/mod.rs +++ b/crates/consensus/src/transaction/mod.rs @@ -1,3 +1,5 @@ +//! Tramsaction types for Optimism. + mod deposit; pub use deposit::TxDeposit; @@ -18,3 +20,32 @@ pub use source::{ pub(super) mod serde_bincode_compat { pub use super::deposit::serde_bincode_compat::TxDeposit; } + +use alloy_primitives::B256; + +/// A trait representing a deposit transaction with specific attributes. +pub trait DepositTransaction { + /// Returns the hash that uniquely identifies the source of the deposit. + /// + /// # Returns + /// An `Option` containing the source hash if available. + fn source_hash(&self) -> Option; + + /// Returns the optional mint value of the deposit transaction. + /// + /// # Returns + /// An `Option` representing the ETH value to mint on L2, if any. + fn mint(&self) -> Option; + + /// Indicates whether the transaction is exempt from the L2 gas limit. + /// + /// # Returns + /// A `bool` indicating if the transaction is a system transaction. + fn is_system_transaction(&self) -> bool; + + /// Checks if the transaction is a deposit transaction. + /// + /// # Returns + /// A `bool` that is always `true` for deposit transactions. + fn is_deposit(&self) -> bool; +}