mega_evme/common/
tx_override.rs1use std::cell::RefCell;
7
8use alloy_primitives::{Address, Bytes, U256};
9use clap::Args;
10use mega_evm::{
11 alloy_evm::{IntoTxEnv, RecoveredTx},
12 MegaTransaction,
13};
14
15use super::{load_hex, parse_ether_value, Result};
16
17thread_local! {
19 static INPUT_OVERRIDE: RefCell<Option<Bytes>> = const { RefCell::new(None) };
20}
21
22#[derive(Args, Debug, Clone, Default)]
24#[command(next_help_heading = "Transaction Override Options")]
25pub struct TxOverrideArgs {
26 #[arg(long = "override.gas-limit", visible_aliases = ["override.gaslimit"], value_name = "GAS")]
28 pub gas_limit: Option<u64>,
29
30 #[arg(long = "override.value", value_name = "VALUE")]
34 pub value: Option<String>,
35
36 #[arg(long = "override.input", visible_aliases = ["override.data"], value_name = "HEX")]
38 pub input: Option<String>,
39
40 #[arg(long = "override.input-file", visible_aliases = ["override.data-file"], value_name = "FILE")]
42 pub input_file: Option<String>,
43}
44
45impl TxOverrideArgs {
46 pub fn has_overrides(&self) -> bool {
48 self.gas_limit.is_some() ||
49 self.value.is_some() ||
50 self.input.is_some() ||
51 self.input_file.is_some()
52 }
53
54 pub fn wrap<T: Copy>(&self, tx: T) -> Result<OverriddenTx<T>> {
56 let has_input_override =
58 if let Some(bytes) = load_hex(self.input.clone(), self.input_file.clone())? {
59 INPUT_OVERRIDE.with(|cell| cell.borrow_mut().replace(bytes));
60 true
61 } else {
62 INPUT_OVERRIDE.with(|cell| cell.borrow_mut().take());
63 false
64 };
65
66 Ok(OverriddenTx {
67 inner: tx,
68 overrides: TxOverrides {
69 gas_limit: self.gas_limit,
70 value: self.value.as_deref().map(parse_ether_value).transpose()?,
71 has_input_override,
72 },
73 })
74 }
75}
76
77#[derive(Debug, Clone, Copy, Default)]
83pub struct TxOverrides {
84 pub gas_limit: Option<u64>,
86 pub value: Option<U256>,
88 pub has_input_override: bool,
90}
91
92impl TxOverrides {
93 pub fn apply(&self, tx: &mut MegaTransaction) {
95 if let Some(gas_limit) = self.gas_limit {
96 tx.base.gas_limit = gas_limit;
97 }
98 if let Some(value) = self.value {
99 tx.base.value = value;
100 }
101 if self.has_input_override {
102 if let Some(input) = INPUT_OVERRIDE.with(|cell| cell.borrow().clone()) {
103 tx.base.data = input;
104 }
105 }
106 }
107}
108
109#[derive(Debug, Clone, Copy)]
114pub struct OverriddenTx<T: Copy> {
115 inner: T,
116 overrides: TxOverrides,
117}
118
119impl<T: Copy> OverriddenTx<T> {
120 pub fn inner(&self) -> &T {
122 &self.inner
123 }
124}
125
126impl<T: IntoTxEnv<MegaTransaction> + Copy> IntoTxEnv<MegaTransaction> for OverriddenTx<T> {
128 fn into_tx_env(self) -> MegaTransaction {
129 let mut tx = self.inner.into_tx_env();
130 self.overrides.apply(&mut tx);
131 tx
132 }
133}
134
135impl<Tx, T: RecoveredTx<Tx> + Copy> RecoveredTx<Tx> for OverriddenTx<T> {
137 fn tx(&self) -> &Tx {
138 self.inner.tx()
139 }
140
141 fn signer(&self) -> &Address {
142 self.inner.signer()
143 }
144}