1use alloy_primitives::{Address, B256, Bytes, U256};
4use revm::{
5 context::{Transaction, TxEnv},
6 context_interface::{
7 either::Either,
8 transaction::{AccessList, RecoveredAuthorization, SignedAuthorization},
9 },
10 primitives::TxKind,
11};
12use tempo_revm::TempoTxEnv;
13
14#[cfg(feature = "optimism")]
15use op_revm::transaction::deposit::DEPOSIT_TRANSACTION_TYPE;
16
17pub trait FoundryTransaction: Transaction {
20 fn set_tx_type(&mut self, tx_type: u8);
22
23 fn set_caller(&mut self, caller: Address);
25
26 fn set_gas_limit(&mut self, gas_limit: u64);
28
29 fn set_gas_price(&mut self, gas_price: u128);
31
32 fn set_kind(&mut self, kind: TxKind);
34
35 fn set_value(&mut self, value: U256);
37
38 fn set_data(&mut self, data: Bytes);
40
41 fn set_nonce(&mut self, nonce: u64);
43
44 fn set_chain_id(&mut self, chain_id: Option<u64>);
46
47 fn set_access_list(&mut self, access_list: AccessList);
49
50 fn authorization_list_mut(
52 &mut self,
53 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>>;
54
55 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>);
57
58 fn set_blob_hashes(&mut self, blob_hashes: Vec<B256>);
60
61 fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128);
63
64 fn set_signed_authorization(&mut self, auth: Vec<SignedAuthorization>) {
66 *self.authorization_list_mut() = auth.into_iter().map(Either::Left).collect();
67 }
68
69 fn enveloped_tx(&self) -> Option<&Bytes> {
73 None
74 }
75
76 fn set_enveloped_tx(&mut self, _bytes: Bytes) {}
78
79 fn source_hash(&self) -> Option<B256> {
81 None
82 }
83
84 fn set_source_hash(&mut self, _source_hash: B256) {}
86
87 fn mint(&self) -> Option<u128> {
89 None
90 }
91
92 fn set_mint(&mut self, _mint: u128) {}
94
95 fn is_system_transaction(&self) -> bool {
97 false
98 }
99
100 fn set_system_transaction(&mut self, _is_system_transaction: bool) {}
102
103 fn is_deposit(&self) -> bool {
105 #[cfg(feature = "optimism")]
106 {
107 self.tx_type() == DEPOSIT_TRANSACTION_TYPE
108 }
109 #[cfg(not(feature = "optimism"))]
110 {
111 false
112 }
113 }
114
115 fn fee_token(&self) -> Option<Address> {
119 None
120 }
121
122 fn set_fee_token(&mut self, _token: Option<Address>) {}
124
125 fn fee_payer(&self) -> Option<Option<Address>> {
127 None
128 }
129
130 fn set_fee_payer(&mut self, _payer: Option<Option<Address>>) {}
132}
133
134impl FoundryTransaction for TxEnv {
135 fn set_tx_type(&mut self, tx_type: u8) {
136 self.tx_type = tx_type;
137 }
138
139 fn set_caller(&mut self, caller: Address) {
140 self.caller = caller;
141 }
142
143 fn set_gas_limit(&mut self, gas_limit: u64) {
144 self.gas_limit = gas_limit;
145 }
146
147 fn set_gas_price(&mut self, gas_price: u128) {
148 self.gas_price = gas_price;
149 }
150
151 fn set_kind(&mut self, kind: TxKind) {
152 self.kind = kind;
153 }
154
155 fn set_value(&mut self, value: U256) {
156 self.value = value;
157 }
158
159 fn set_data(&mut self, data: Bytes) {
160 self.data = data;
161 }
162
163 fn set_nonce(&mut self, nonce: u64) {
164 self.nonce = nonce;
165 }
166
167 fn set_chain_id(&mut self, chain_id: Option<u64>) {
168 self.chain_id = chain_id;
169 }
170
171 fn set_access_list(&mut self, access_list: AccessList) {
172 self.access_list = access_list;
173 }
174
175 fn authorization_list_mut(
176 &mut self,
177 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>> {
178 &mut self.authorization_list
179 }
180
181 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>) {
182 self.gas_priority_fee = gas_priority_fee;
183 }
184
185 fn set_blob_hashes(&mut self, blob_hashes: Vec<B256>) {
186 self.blob_hashes = blob_hashes;
187 }
188
189 fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
190 self.max_fee_per_blob_gas = max_fee_per_blob_gas;
191 }
192}
193
194impl FoundryTransaction for TempoTxEnv {
195 fn set_tx_type(&mut self, tx_type: u8) {
196 self.inner.set_tx_type(tx_type);
197 }
198
199 fn set_caller(&mut self, caller: Address) {
200 self.inner.set_caller(caller);
201 }
202
203 fn set_gas_limit(&mut self, gas_limit: u64) {
204 self.inner.set_gas_limit(gas_limit);
205 }
206
207 fn set_gas_price(&mut self, gas_price: u128) {
208 self.inner.set_gas_price(gas_price);
209 }
210
211 fn set_kind(&mut self, kind: TxKind) {
212 self.inner.set_kind(kind);
213 if let Some(call) =
214 self.tempo_tx_env.as_deref_mut().and_then(|env| env.aa_calls.first_mut())
215 {
216 call.to = kind;
217 }
218 }
219
220 fn set_value(&mut self, value: U256) {
221 self.inner.set_value(value);
222 if let Some(call) =
223 self.tempo_tx_env.as_deref_mut().and_then(|env| env.aa_calls.first_mut())
224 {
225 call.value = value;
226 }
227 }
228
229 fn set_data(&mut self, data: Bytes) {
230 self.inner.set_data(data.clone());
231 if let Some(call) =
232 self.tempo_tx_env.as_deref_mut().and_then(|env| env.aa_calls.first_mut())
233 {
234 call.input = data;
235 }
236 }
237
238 fn set_nonce(&mut self, nonce: u64) {
239 self.inner.set_nonce(nonce);
240 }
241
242 fn set_chain_id(&mut self, chain_id: Option<u64>) {
243 self.inner.set_chain_id(chain_id);
244 }
245
246 fn set_access_list(&mut self, access_list: AccessList) {
247 self.inner.set_access_list(access_list);
248 }
249
250 fn authorization_list_mut(
251 &mut self,
252 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>> {
253 self.inner.authorization_list_mut()
254 }
255
256 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>) {
257 self.inner.set_gas_priority_fee(gas_priority_fee);
258 }
259
260 fn set_blob_hashes(&mut self, _blob_hashes: Vec<B256>) {}
261
262 fn set_max_fee_per_blob_gas(&mut self, _max_fee_per_blob_gas: u128) {}
263
264 fn fee_token(&self) -> Option<Address> {
265 self.fee_token
266 }
267
268 fn set_fee_token(&mut self, token: Option<Address>) {
269 self.fee_token = token;
270 }
271
272 fn fee_payer(&self) -> Option<Option<Address>> {
273 self.fee_payer
274 }
275
276 fn set_fee_payer(&mut self, payer: Option<Option<Address>>) {
277 self.fee_payer = payer;
278 }
279}
280
281#[cfg(feature = "base")]
282mod base {
283 use super::*;
284 use base_common_evm::{BaseTransaction, BaseTxTr, DEPOSIT_TRANSACTION_TYPE};
285
286 impl<TX: FoundryTransaction> FoundryTransaction for BaseTransaction<TX> {
287 fn set_tx_type(&mut self, tx_type: u8) {
288 self.base.set_tx_type(tx_type);
289 }
290
291 fn set_caller(&mut self, caller: Address) {
292 self.base.set_caller(caller);
293 }
294
295 fn set_gas_limit(&mut self, gas_limit: u64) {
296 self.base.set_gas_limit(gas_limit);
297 }
298
299 fn set_gas_price(&mut self, gas_price: u128) {
300 self.base.set_gas_price(gas_price);
301 }
302
303 fn set_kind(&mut self, kind: TxKind) {
304 self.base.set_kind(kind);
305 }
306
307 fn set_value(&mut self, value: U256) {
308 self.base.set_value(value);
309 }
310
311 fn set_data(&mut self, data: Bytes) {
312 self.base.set_data(data);
313 }
314
315 fn set_nonce(&mut self, nonce: u64) {
316 self.base.set_nonce(nonce);
317 }
318
319 fn set_chain_id(&mut self, chain_id: Option<u64>) {
320 self.base.set_chain_id(chain_id);
321 }
322
323 fn set_access_list(&mut self, access_list: AccessList) {
324 self.base.set_access_list(access_list);
325 }
326
327 fn authorization_list_mut(
328 &mut self,
329 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>> {
330 self.base.authorization_list_mut()
331 }
332
333 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>) {
334 self.base.set_gas_priority_fee(gas_priority_fee);
335 }
336
337 fn set_blob_hashes(&mut self, blob_hashes: Vec<B256>) {
338 self.base.set_blob_hashes(blob_hashes);
339 }
340
341 fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
342 self.base.set_max_fee_per_blob_gas(max_fee_per_blob_gas);
343 }
344
345 fn enveloped_tx(&self) -> Option<&Bytes> {
346 BaseTxTr::enveloped_tx(self)
347 }
348
349 fn set_enveloped_tx(&mut self, bytes: Bytes) {
350 self.enveloped_tx = Some(bytes);
351 }
352
353 fn source_hash(&self) -> Option<B256> {
354 BaseTxTr::source_hash(self)
355 }
356
357 fn set_source_hash(&mut self, source_hash: B256) {
358 self.deposit.source_hash = source_hash;
359 }
360
361 fn mint(&self) -> Option<u128> {
362 BaseTxTr::mint(self)
363 }
364
365 fn set_mint(&mut self, mint: u128) {
366 self.deposit.mint = Some(mint);
367 }
368
369 fn is_system_transaction(&self) -> bool {
370 BaseTxTr::is_system_transaction(self)
371 }
372
373 fn set_system_transaction(&mut self, is_system_transaction: bool) {
374 self.deposit.is_system_transaction = is_system_transaction;
375 }
376
377 fn is_deposit(&self) -> bool {
378 self.tx_type() == DEPOSIT_TRANSACTION_TYPE
379 }
380 }
381}
382
383#[cfg(feature = "optimism")]
384mod optimism {
385 use super::*;
386 use alloy_op_evm::OpTx;
387 use op_revm::{OpTransaction, transaction::OpTxTr};
388
389 impl<TX: FoundryTransaction> FoundryTransaction for OpTransaction<TX> {
390 fn set_tx_type(&mut self, tx_type: u8) {
391 self.base.set_tx_type(tx_type);
392 }
393
394 fn set_caller(&mut self, caller: Address) {
395 self.base.set_caller(caller);
396 }
397
398 fn set_gas_limit(&mut self, gas_limit: u64) {
399 self.base.set_gas_limit(gas_limit);
400 }
401
402 fn set_gas_price(&mut self, gas_price: u128) {
403 self.base.set_gas_price(gas_price);
404 }
405
406 fn set_kind(&mut self, kind: TxKind) {
407 self.base.set_kind(kind);
408 }
409
410 fn set_value(&mut self, value: U256) {
411 self.base.set_value(value);
412 }
413
414 fn set_data(&mut self, data: Bytes) {
415 self.base.set_data(data);
416 }
417
418 fn set_nonce(&mut self, nonce: u64) {
419 self.base.set_nonce(nonce);
420 }
421
422 fn set_chain_id(&mut self, chain_id: Option<u64>) {
423 self.base.set_chain_id(chain_id);
424 }
425
426 fn set_access_list(&mut self, access_list: AccessList) {
427 self.base.set_access_list(access_list);
428 }
429
430 fn authorization_list_mut(
431 &mut self,
432 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>> {
433 self.base.authorization_list_mut()
434 }
435
436 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>) {
437 self.base.set_gas_priority_fee(gas_priority_fee);
438 }
439
440 fn set_blob_hashes(&mut self, _blob_hashes: Vec<B256>) {}
441
442 fn set_max_fee_per_blob_gas(&mut self, _max_fee_per_blob_gas: u128) {}
443
444 fn enveloped_tx(&self) -> Option<&Bytes> {
445 OpTxTr::enveloped_tx(self)
446 }
447
448 fn set_enveloped_tx(&mut self, bytes: Bytes) {
449 self.enveloped_tx = Some(bytes);
450 }
451
452 fn source_hash(&self) -> Option<B256> {
453 OpTxTr::source_hash(self)
454 }
455
456 fn set_source_hash(&mut self, source_hash: B256) {
457 if self.tx_type() == DEPOSIT_TRANSACTION_TYPE {
458 self.deposit.source_hash = source_hash;
459 }
460 }
461
462 fn mint(&self) -> Option<u128> {
463 OpTxTr::mint(self)
464 }
465
466 fn set_mint(&mut self, mint: u128) {
467 if self.tx_type() == DEPOSIT_TRANSACTION_TYPE {
468 self.deposit.mint = Some(mint);
469 }
470 }
471
472 fn is_system_transaction(&self) -> bool {
473 OpTxTr::is_system_transaction(self)
474 }
475
476 fn set_system_transaction(&mut self, is_system_transaction: bool) {
477 if self.tx_type() == DEPOSIT_TRANSACTION_TYPE {
478 self.deposit.is_system_transaction = is_system_transaction;
479 }
480 }
481 }
482
483 impl FoundryTransaction for OpTx {
484 fn set_tx_type(&mut self, tx_type: u8) {
485 self.0.set_tx_type(tx_type);
486 }
487
488 fn set_caller(&mut self, caller: Address) {
489 self.0.set_caller(caller);
490 }
491
492 fn set_gas_limit(&mut self, gas_limit: u64) {
493 self.0.set_gas_limit(gas_limit);
494 }
495
496 fn set_gas_price(&mut self, gas_price: u128) {
497 self.0.set_gas_price(gas_price);
498 }
499
500 fn set_kind(&mut self, kind: TxKind) {
501 self.0.set_kind(kind);
502 }
503
504 fn set_value(&mut self, value: U256) {
505 self.0.set_value(value);
506 }
507
508 fn set_data(&mut self, data: Bytes) {
509 self.0.set_data(data);
510 }
511
512 fn set_nonce(&mut self, nonce: u64) {
513 self.0.set_nonce(nonce);
514 }
515
516 fn set_chain_id(&mut self, chain_id: Option<u64>) {
517 self.0.set_chain_id(chain_id);
518 }
519
520 fn set_access_list(&mut self, access_list: AccessList) {
521 self.0.set_access_list(access_list);
522 }
523
524 fn authorization_list_mut(
525 &mut self,
526 ) -> &mut Vec<Either<SignedAuthorization, RecoveredAuthorization>> {
527 self.0.authorization_list_mut()
528 }
529
530 fn set_gas_priority_fee(&mut self, gas_priority_fee: Option<u128>) {
531 self.0.set_gas_priority_fee(gas_priority_fee);
532 }
533
534 fn set_blob_hashes(&mut self, _blob_hashes: Vec<B256>) {}
535
536 fn set_max_fee_per_blob_gas(&mut self, _max_fee_per_blob_gas: u128) {}
537
538 fn enveloped_tx(&self) -> Option<&Bytes> {
539 FoundryTransaction::enveloped_tx(&self.0)
540 }
541
542 fn set_enveloped_tx(&mut self, bytes: Bytes) {
543 self.0.set_enveloped_tx(bytes);
544 }
545
546 fn source_hash(&self) -> Option<B256> {
547 FoundryTransaction::source_hash(&self.0)
548 }
549
550 fn set_source_hash(&mut self, source_hash: B256) {
551 self.0.set_source_hash(source_hash);
552 }
553
554 fn mint(&self) -> Option<u128> {
555 FoundryTransaction::mint(&self.0)
556 }
557
558 fn set_mint(&mut self, mint: u128) {
559 self.0.set_mint(mint);
560 }
561
562 fn is_system_transaction(&self) -> bool {
563 FoundryTransaction::is_system_transaction(&self.0)
564 }
565
566 fn set_system_transaction(&mut self, is_system_transaction: bool) {
567 self.0.set_system_transaction(is_system_transaction);
568 }
569 }
570}
571
572#[cfg(test)]
573mod tests {
574 use super::*;
575 use tempo_alloy::primitives::transaction::Call;
576
577 #[test]
578 fn tempo_tx_env_setters_update_aa_call_payload() {
579 let old_to = TxKind::Call(Address::with_last_byte(0xAA));
580 let new_to = TxKind::Create;
581 let new_value = U256::from(123);
582 let new_input = Bytes::from_static(b"local bytecode");
583
584 let mut tx_env = TempoTxEnv {
585 inner: TxEnv {
586 kind: old_to,
587 value: U256::ONE,
588 data: Bytes::from_static(b"original bytecode"),
589 ..Default::default()
590 },
591 tempo_tx_env: Some(Box::new(tempo_revm::TempoBatchCallEnv {
592 aa_calls: vec![Call {
593 to: old_to,
594 value: U256::ONE,
595 input: Bytes::from_static(b"original bytecode"),
596 }],
597 ..Default::default()
598 })),
599 ..Default::default()
600 };
601
602 tx_env.set_kind(new_to);
603 tx_env.set_value(new_value);
604 tx_env.set_data(new_input.clone());
605
606 assert_eq!(tx_env.inner.kind, new_to);
607 assert_eq!(tx_env.inner.value, new_value);
608 assert_eq!(tx_env.inner.data, new_input);
609
610 let call = &tx_env.tempo_tx_env.as_ref().unwrap().aa_calls[0];
611 assert_eq!(call.to, new_to);
612 assert_eq!(call.value, new_value);
613 assert_eq!(call.input, new_input);
614 }
615}