signet_evm/sys/
transact.rs1use crate::sys::{MeteredSysTx, SysBase, SysTx, TransactSysLog};
2use alloy::{
3 consensus::{EthereumTxEnvelope, Transaction},
4 hex,
5 primitives::{utils::format_ether, Address, Bytes, Log, TxKind, U256},
6};
7use core::fmt;
8use signet_extract::ExtractedEvent;
9use signet_types::{primitives::TransactionSigned, MagicSig, MagicSigInfo};
10use signet_zenith::Transactor;
11use trevm::{revm::context::TxEnv, Tx};
12
13#[derive(PartialEq, Eq)]
15pub struct TransactSysTx {
16 tx: TransactionSigned,
18
19 nonce: Option<u64>,
21
22 magic_sig: MagicSig,
25}
26
27impl TransactSysTx {
28 pub fn new<R>(transact: &ExtractedEvent<'_, R, Transactor::Transact>, aliased: bool) -> Self {
30 let magic_sig = transact.magic_sig(aliased);
31 let tx = transact.make_transaction(0, aliased);
32 Self { tx, nonce: None, magic_sig }
33 }
34
35 pub fn is_aliased(&self) -> bool {
38 match self.magic_sig.ty {
39 MagicSigInfo::Transact { aliased, .. } => aliased,
40 _ => unreachable!(),
41 }
42 }
43
44 fn make_sys_log(&self) -> TransactSysLog {
46 TransactSysLog {
47 txHash: self.magic_sig.txid,
48 logIndex: self.magic_sig.event_idx as u64,
49 sender: self.evm_sender(),
50 value: self.tx.value(),
51 gas: U256::from(self.tx.gas_limit()),
52 maxFeePerGas: U256::from(self.tx.max_fee_per_gas()),
53 }
54 }
55}
56
57impl fmt::Debug for TransactSysTx {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 f.debug_struct("TransactSysTx")
61 .field("transact", &self.tx)
62 .field("nonce", &self.nonce)
63 .field("magic_sig", &self.magic_sig)
64 .finish()
65 }
66}
67
68impl Clone for TransactSysTx {
70 fn clone(&self) -> Self {
71 Self { tx: self.tx.clone(), nonce: self.nonce, magic_sig: self.magic_sig }
72 }
73}
74
75impl Tx for TransactSysTx {
76 fn fill_tx_env(&self, tx_env: &mut TxEnv) {
77 self.tx.as_eip1559().unwrap().fill_tx_env(tx_env);
78 tx_env.caller = self.magic_sig.rollup_sender();
79 }
80}
81
82impl SysBase for TransactSysTx {
83 fn name() -> &'static str {
84 "TransactSysTx"
85 }
86
87 fn description(&self) -> String {
88 let is_aliased = if self.is_aliased() { " (aliased)" } else { "" };
89
90 format!(
91 "Transact from {}{is_aliased} to {} with value {} and {} bytes of input data: `0x{}{}`",
92 self.magic_sig.rollup_sender(),
93 self.tx.to().expect("creates not allowed"),
94 format_ether(self.tx.value()),
95 self.tx.input().len(),
96 self.tx.input().chunks(4).next().map(hex::encode).unwrap_or_default(),
97 if self.tx.input().len() > 4 { "..." } else { "" },
98 )
99 }
100
101 fn has_nonce(&self) -> bool {
102 self.nonce.is_some()
103 }
104
105 fn populate_nonce(&mut self, nonce: u64) {
106 let EthereumTxEnvelope::Eip1559(signed) = &mut self.tx else {
110 unreachable!("new sets this to 1559");
111 };
112 signed.tx_mut().nonce = nonce;
113 self.nonce = Some(nonce);
114 }
115
116 fn produce_transaction(&self) -> TransactionSigned {
117 self.tx.clone()
118 }
119
120 fn produce_log(&self) -> Log {
121 self.make_sys_log().into()
122 }
123
124 fn evm_sender(&self) -> Address {
125 self.magic_sig.rollup_sender()
126 }
127}
128
129impl SysTx for TransactSysTx {
130 fn callee(&self) -> TxKind {
131 self.tx.kind()
132 }
133
134 fn input(&self) -> Bytes {
135 self.tx.input().clone()
136 }
137
138 fn value(&self) -> U256 {
139 self.tx.value()
140 }
141}
142
143impl MeteredSysTx for TransactSysTx {
144 fn gas_limit(&self) -> u128 {
145 self.tx.gas_limit() as u128
146 }
147
148 fn max_fee_per_gas(&self) -> u128 {
149 self.tx.max_fee_per_gas()
150 }
151}