revm_optimism/transaction/
abstraction.rs

1use super::deposit::{DepositTransaction, DepositTransactionParts};
2use auto_impl::auto_impl;
3use revm::{
4    context::TxEnv,
5    context_interface::transaction::Transaction,
6    primitives::{Address, Bytes, TxKind, B256, U256},
7};
8use std::vec;
9
10#[auto_impl(&, &mut, Box, Arc)]
11pub trait OpTxTr: Transaction + DepositTransaction {
12    fn enveloped_tx(&self) -> Option<&Bytes>;
13}
14
15#[derive(Clone, Debug, PartialEq, Eq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct OpTransaction<T: Transaction> {
18    pub base: T,
19    /// An enveloped EIP-2718 typed transaction
20    ///
21    /// This is used to compute the L1 tx cost using the L1 block info, as
22    /// opposed to requiring downstream apps to compute the cost
23    /// externally.
24    pub enveloped_tx: Option<Bytes>,
25    pub deposit: DepositTransactionParts,
26}
27
28impl<T: Transaction> OpTransaction<T> {
29    pub fn new(base: T) -> Self {
30        Self {
31            base,
32            enveloped_tx: None,
33            deposit: DepositTransactionParts::default(),
34        }
35    }
36}
37
38impl Default for OpTransaction<TxEnv> {
39    fn default() -> Self {
40        Self {
41            base: TxEnv::default(),
42            enveloped_tx: Some(vec![0x00].into()),
43            deposit: DepositTransactionParts::default(),
44        }
45    }
46}
47
48impl<T: Transaction> Transaction for OpTransaction<T> {
49    type AccessList = T::AccessList;
50    type Authorization = T::Authorization;
51
52    fn tx_type(&self) -> u8 {
53        self.base.tx_type()
54    }
55
56    fn caller(&self) -> Address {
57        self.base.caller()
58    }
59
60    fn gas_limit(&self) -> u64 {
61        self.base.gas_limit()
62    }
63
64    fn value(&self) -> U256 {
65        self.base.value()
66    }
67
68    fn input(&self) -> &Bytes {
69        self.base.input()
70    }
71
72    fn nonce(&self) -> u64 {
73        self.base.nonce()
74    }
75
76    fn kind(&self) -> TxKind {
77        self.base.kind()
78    }
79
80    fn chain_id(&self) -> Option<u64> {
81        self.base.chain_id()
82    }
83
84    fn access_list(&self) -> Option<&Self::AccessList> {
85        self.base.access_list()
86    }
87
88    fn max_priority_fee_per_gas(&self) -> Option<u128> {
89        self.base.max_priority_fee_per_gas()
90    }
91
92    fn max_fee_per_gas(&self) -> u128 {
93        self.base.max_fee_per_gas()
94    }
95
96    fn gas_price(&self) -> u128 {
97        self.base.gas_price()
98    }
99
100    fn blob_versioned_hashes(&self) -> &[B256] {
101        self.base.blob_versioned_hashes()
102    }
103
104    fn max_fee_per_blob_gas(&self) -> u128 {
105        self.base.max_fee_per_blob_gas()
106    }
107
108    fn effective_gas_price(&self, base_fee: u128) -> u128 {
109        self.base.effective_gas_price(base_fee)
110    }
111
112    fn authorization_list_len(&self) -> usize {
113        self.base.authorization_list_len()
114    }
115
116    fn authorization_list(&self) -> impl Iterator<Item = &Self::Authorization> {
117        self.base.authorization_list()
118    }
119}
120
121impl<T: Transaction> DepositTransaction for OpTransaction<T> {
122    fn source_hash(&self) -> B256 {
123        self.deposit.source_hash
124    }
125
126    fn mint(&self) -> Option<u128> {
127        self.deposit.mint
128    }
129
130    fn is_system_transaction(&self) -> bool {
131        self.deposit.is_system_transaction
132    }
133}
134
135impl<T: Transaction> OpTxTr for OpTransaction<T> {
136    fn enveloped_tx(&self) -> Option<&Bytes> {
137        self.enveloped_tx.as_ref()
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use crate::transaction::deposit::DEPOSIT_TRANSACTION_TYPE;
144
145    use super::*;
146    use revm::primitives::{Address, B256};
147
148    #[test]
149    fn test_deposit_transaction_fields() {
150        let op_tx = OpTransaction {
151            base: TxEnv {
152                tx_type: DEPOSIT_TRANSACTION_TYPE,
153                gas_limit: 10,
154                gas_price: 100,
155                gas_priority_fee: Some(5),
156                ..Default::default()
157            },
158            enveloped_tx: None,
159            deposit: DepositTransactionParts {
160                is_system_transaction: false,
161                mint: Some(0u128),
162                source_hash: B256::default(),
163            },
164        };
165        // Verify transaction type
166        assert_eq!(op_tx.tx_type(), DEPOSIT_TRANSACTION_TYPE);
167        // Verify common fields access
168        assert_eq!(op_tx.gas_limit(), 10);
169        assert_eq!(op_tx.kind(), revm::primitives::TxKind::Call(Address::ZERO));
170        // Verify gas related calculations
171        assert_eq!(op_tx.effective_gas_price(90), 95);
172        assert_eq!(op_tx.max_fee_per_gas(), 100);
173    }
174}