1use super::run::fetch_contracts_bytecode_from_trace;
2use crate::{
3 Cast,
4 debug::handle_traces,
5 traces::TraceKind,
6 tx::{CastTxBuilder, SenderKind},
7};
8use alloy_ens::NameOrAddress;
9use alloy_network::{Network, NetworkTransactionBuilder, TransactionBuilder};
10use alloy_primitives::{Address, B256, Bytes, TxKind, U256, hex, map::HashMap};
11use alloy_provider::Provider;
12use alloy_rpc_types::{
13 BlockId, BlockNumberOrTag, BlockOverrides,
14 state::{StateOverride, StateOverridesBuilder},
15};
16use clap::Parser;
17use eyre::Result;
18use foundry_cli::{
19 opts::{ChainValueParser, RpcOpts, TransactionOpts},
20 utils::{LoadConfig, TraceResult, parse_ether_value},
21};
22use foundry_common::{
23 FoundryTransactionBuilder,
24 abi::{encode_function_args, get_func},
25 provider::{ProviderBuilder, curl_transport::generate_curl_command},
26 sh_println, shell,
27};
28use foundry_compilers::artifacts::EvmVersion;
29use foundry_config::{
30 Chain, Config,
31 figment::{
32 self, Metadata, Profile,
33 value::{Dict, Map},
34 },
35};
36#[cfg(feature = "optimism")]
37use foundry_evm::core::evm::OpEvmNetwork;
38use foundry_evm::{
39 core::{
40 FoundryBlock, FoundryTransaction,
41 evm::{EthEvmNetwork, FoundryEvmNetwork, TempoEvmNetwork},
42 },
43 executors::TracingExecutor,
44 opts::EvmOpts,
45 traces::{InternalTraceMode, TraceMode},
46};
47use foundry_wallets::WalletOpts;
48use regex::Regex;
49use std::{str::FromStr, sync::LazyLock};
50
51static OVERRIDE_PATTERN: LazyLock<Regex> =
54 LazyLock::new(|| Regex::new(r"^([^:]+):([^:]+):([^:]+)$").unwrap());
55
56#[derive(Debug, Parser)]
78pub struct CallArgs {
79 #[arg(value_parser = NameOrAddress::from_str)]
81 to: Option<NameOrAddress>,
82
83 sig: Option<String>,
85
86 #[arg(allow_negative_numbers = true)]
88 args: Vec<String>,
89
90 #[arg(
92 long,
93 conflicts_with_all = &["sig", "args"]
94 )]
95 data: Option<String>,
96
97 #[arg(long, default_value_t = false)]
99 trace: bool,
100
101 #[arg(long, default_value_t = false, requires = "trace")]
104 disable_labels: bool,
105
106 #[arg(long, requires = "trace")]
109 debug: bool,
110
111 #[arg(long, requires = "trace")]
118 decode_internal: bool,
119
120 #[arg(long, requires = "trace")]
123 labels: Vec<String>,
124
125 #[arg(long, requires = "trace")]
128 evm_version: Option<EvmVersion>,
129
130 #[arg(long, short)]
134 block: Option<BlockId>,
135
136 #[command(subcommand)]
137 command: Option<CallSubcommands>,
138
139 #[command(flatten)]
140 tx: TransactionOpts,
141
142 #[command(flatten)]
143 rpc: RpcOpts,
144
145 #[command(flatten)]
146 wallet: WalletOpts,
147
148 #[arg(
149 short,
150 long,
151 alias = "chain-id",
152 env = "CHAIN",
153 value_parser = ChainValueParser::default(),
154 )]
155 pub chain: Option<Chain>,
156
157 #[arg(long, visible_alias = "la")]
159 pub with_local_artifacts: bool,
160
161 #[arg(long = "override-balance", value_name = "ADDRESS:BALANCE", value_delimiter = ',')]
164 pub balance_overrides: Option<Vec<String>>,
165
166 #[arg(long = "override-nonce", value_name = "ADDRESS:NONCE", value_delimiter = ',')]
169 pub nonce_overrides: Option<Vec<String>>,
170
171 #[arg(long = "override-code", value_name = "ADDRESS:CODE", value_delimiter = ',')]
174 pub code_overrides: Option<Vec<String>>,
175
176 #[arg(long = "override-state", value_name = "ADDRESS:SLOT:VALUE", value_delimiter = ',')]
179 pub state_overrides: Option<Vec<String>>,
180
181 #[arg(long = "override-state-diff", value_name = "ADDRESS:SLOT:VALUE", value_delimiter = ',')]
184 pub state_diff_overrides: Option<Vec<String>>,
185
186 #[arg(long = "block.time", value_name = "TIME")]
188 pub block_time: Option<u64>,
189
190 #[arg(long = "block.number", value_name = "NUMBER")]
192 pub block_number: Option<u64>,
193}
194
195#[derive(Debug, Parser)]
196pub enum CallSubcommands {
197 #[command(name = "--create")]
199 Create {
200 code: String,
202
203 sig: Option<String>,
205
206 #[arg(allow_negative_numbers = true)]
208 args: Vec<String>,
209
210 #[arg(long, value_parser = parse_ether_value)]
216 value: Option<U256>,
217 },
218}
219
220impl CallArgs {
221 pub async fn run(self) -> Result<()> {
222 if self.rpc.curl {
224 return self.run_curl().await;
225 }
226 if self.tx.tempo.is_tempo() {
227 return self.run_with_network::<TempoEvmNetwork>().await;
228 }
229
230 let figment = self.rpc.clone().into_figment(self.with_local_artifacts).merge(&self);
231 let mut evm_opts = figment.extract::<EvmOpts>()?;
232 if let Some(chain) = self.chain {
233 evm_opts.networks = evm_opts.networks.with_chain_id(chain.id());
234 }
235 evm_opts.infer_network_from_fork().await;
236
237 if evm_opts.networks.is_tempo() {
238 return self.run_with_network::<TempoEvmNetwork>().await;
239 }
240
241 #[cfg(feature = "optimism")]
242 if evm_opts.networks.is_optimism() {
243 return self.run_with_network::<OpEvmNetwork>().await;
244 }
245
246 self.run_with_network::<EthEvmNetwork>().await
247 }
248
249 pub async fn run_with_network<FEN: FoundryEvmNetwork>(self) -> Result<()>
250 where
251 <FEN::Network as Network>::TransactionRequest: FoundryTransactionBuilder<FEN::Network>,
252 {
253 let figment = self.rpc.clone().into_figment(self.with_local_artifacts).merge(&self);
254 let evm_opts = figment.extract::<EvmOpts>()?;
255 let mut config = Config::from_provider(figment)?.sanitized();
256 let state_overrides = self.get_state_overrides()?;
257 let block_overrides = self.get_block_overrides()?;
258
259 let Self {
260 to,
261 mut sig,
262 mut args,
263 mut tx,
264 command,
265 block,
266 trace,
267 evm_version,
268 debug,
269 decode_internal,
270 labels,
271 data,
272 with_local_artifacts,
273 disable_labels,
274 wallet,
275 ..
276 } = self;
277
278 if let Some(data) = data {
279 sig = Some(data);
280 }
281
282 let provider = ProviderBuilder::<FEN::Network>::from_config(&config)?.build()?;
283 let sender = SenderKind::from_wallet_opts(wallet).await?;
284 let from = sender.address();
285
286 let code = if let Some(CallSubcommands::Create {
287 code,
288 sig: create_sig,
289 args: create_args,
290 value,
291 }) = command
292 {
293 sig = create_sig;
294 args = create_args;
295 if let Some(value) = value {
296 tx.value = Some(value);
297 }
298 Some(code)
299 } else {
300 None
301 };
302
303 let (tx, func) = CastTxBuilder::new(&provider, tx, &config)
304 .await?
305 .with_to(to)
306 .await?
307 .with_code_sig_and_args(code, sig, args)
308 .await?
309 .raw()
310 .build(sender)
311 .await?;
312
313 if trace {
314 if let Some(BlockId::Number(BlockNumberOrTag::Number(block_number))) = self.block {
315 config.fork_block_number = Some(block_number);
317 }
318
319 let create2_deployer = evm_opts.create2_deployer;
320 let (mut evm_env, tx_env, fork, chain, networks) =
321 TracingExecutor::<FEN>::get_fork_material(&mut config, evm_opts).await?;
322
323 evm_env.cfg_env.disable_block_gas_limit = true;
325 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
326 evm_env.block_env.set_gas_limit(u64::MAX);
327
328 if let Some(block_overrides) = block_overrides {
330 if let Some(number) = block_overrides.number {
331 evm_env.block_env.set_number(number.to());
332 }
333 if let Some(time) = block_overrides.time {
334 evm_env.block_env.set_timestamp(U256::from(time));
335 }
336 }
337
338 let trace_mode = TraceMode::Call
339 .with_debug(debug)
340 .with_decode_internal(if decode_internal {
341 InternalTraceMode::Full
342 } else {
343 InternalTraceMode::None
344 })
345 .with_state_changes(shell::verbosity() > 4);
346 let mut executor = TracingExecutor::<FEN>::new(
347 (evm_env, tx_env),
348 fork,
349 evm_version,
350 trace_mode,
351 networks,
352 create2_deployer,
353 state_overrides,
354 )?;
355
356 let value = tx.value().unwrap_or_default();
357 let input = tx.input().cloned().unwrap_or_default();
358 let tx_kind = tx.kind().expect("set by builder");
359 let env_tx = executor.tx_env_mut();
360
361 if let Some(gas_limit) = tx.gas_limit() {
363 env_tx.set_gas_limit(gas_limit);
364 }
365
366 if let Some(gas_price) = tx.gas_price() {
367 env_tx.set_gas_price(gas_price);
368 }
369
370 if let Some(max_fee_per_gas) = tx.max_fee_per_gas() {
371 env_tx.set_gas_price(max_fee_per_gas);
372 }
373
374 if let Some(max_priority_fee_per_gas) = tx.max_priority_fee_per_gas() {
375 env_tx.set_gas_priority_fee(Some(max_priority_fee_per_gas));
376 }
377
378 if let Some(max_fee_per_blob_gas) = tx.max_fee_per_blob_gas() {
379 env_tx.set_max_fee_per_blob_gas(max_fee_per_blob_gas);
380 }
381
382 if let Some(nonce) = tx.nonce() {
383 env_tx.set_nonce(nonce);
384 }
385
386 env_tx.set_tx_type(tx.output_tx_type().into());
387
388 if let Some(access_list) = tx.access_list().cloned() {
389 env_tx.set_access_list(access_list);
390 }
391
392 if let Some(auth) = tx.authorization_list().cloned() {
393 env_tx.set_signed_authorization(auth);
394 }
395
396 let trace = match tx_kind {
397 TxKind::Create => {
398 let deploy_result = executor.deploy(from, input, value, None);
399 TraceResult::try_from(deploy_result)?
400 }
401 TxKind::Call(to) => TraceResult::from_raw(
402 executor.transact_raw(from, to, input, value)?,
403 TraceKind::Execution,
404 ),
405 };
406
407 let contracts_bytecode = fetch_contracts_bytecode_from_trace(&executor, &trace)?;
408 handle_traces(
409 trace,
410 &config,
411 chain,
412 &contracts_bytecode,
413 labels,
414 with_local_artifacts,
415 debug,
416 decode_internal,
417 disable_labels,
418 None,
419 )
420 .await?;
421
422 return Ok(());
423 }
424
425 let response = Cast::new(&provider)
426 .call(&tx, func.as_ref(), block, state_overrides, block_overrides)
427 .await?;
428
429 if response == "0x"
430 && let Some(contract_address) = tx.to()
431 {
432 let code = provider.get_code_at(contract_address).await?;
433 if code.is_empty() {
434 sh_warn!("Contract code is empty")?;
435 }
436 }
437 sh_println!("{}", response)?;
438
439 Ok(())
440 }
441
442 async fn run_curl(self) -> Result<()> {
444 let config = self.rpc.load_config()?;
445 let url = config.get_rpc_url_or_localhost_http()?;
446 let jwt = config.get_rpc_jwt_secret()?;
447
448 let data = if let Some(data) = &self.data {
450 hex::decode(data)?
451 } else if let Some(sig) = &self.sig {
452 if let Ok(data) = hex::decode(sig) {
454 data
455 } else {
456 let func = get_func(sig)?;
458 encode_function_args(&func, &self.args)?
459 }
460 } else {
461 Vec::new()
462 };
463
464 let to = self.to.as_ref().map(|n| match n {
466 NameOrAddress::Address(addr) => Ok(*addr),
467 NameOrAddress::Name(name) => {
468 eyre::bail!("ENS names are not supported with --curl. Please use a raw address instead of '{}'", name)
469 }
470 }).transpose()?;
471
472 let call_object = serde_json::json!({
474 "to": to,
475 "data": format!("0x{}", hex::encode(&data)),
476 });
477
478 let block_param = self
479 .block
480 .map(|b| serde_json::to_value(b).unwrap_or(serde_json::json!("latest")))
481 .unwrap_or(serde_json::json!("latest"));
482
483 let params = serde_json::json!([call_object, block_param]);
484
485 let curl_cmd = generate_curl_command(
486 url.as_ref(),
487 "eth_call",
488 params,
489 config.eth_rpc_headers.as_deref(),
490 jwt.as_deref(),
491 );
492
493 sh_println!("{}", curl_cmd)?;
494 Ok(())
495 }
496
497 pub fn get_state_overrides(&self) -> eyre::Result<Option<StateOverride>> {
499 if [
501 self.balance_overrides.as_ref(),
502 self.nonce_overrides.as_ref(),
503 self.code_overrides.as_ref(),
504 self.state_overrides.as_ref(),
505 self.state_diff_overrides.as_ref(),
506 ]
507 .iter()
508 .all(Option::is_none)
509 {
510 return Ok(None);
511 }
512
513 let mut state_overrides_builder = StateOverridesBuilder::default();
514
515 for override_str in self.balance_overrides.iter().flatten() {
517 let (addr, balance) = address_value_override(override_str)?;
518 state_overrides_builder =
519 state_overrides_builder.with_balance(addr.parse()?, balance.parse()?);
520 }
521
522 for override_str in self.nonce_overrides.iter().flatten() {
524 let (addr, nonce) = address_value_override(override_str)?;
525 state_overrides_builder =
526 state_overrides_builder.with_nonce(addr.parse()?, nonce.parse()?);
527 }
528
529 for override_str in self.code_overrides.iter().flatten() {
531 let (addr, code_str) = address_value_override(override_str)?;
532 state_overrides_builder =
533 state_overrides_builder.with_code(addr.parse()?, Bytes::from_str(code_str)?);
534 }
535
536 type StateOverrides = HashMap<Address, HashMap<B256, B256>>;
537 let parse_state_overrides =
538 |overrides: &Option<Vec<String>>| -> Result<StateOverrides, eyre::Report> {
539 let mut state_overrides: StateOverrides = StateOverrides::default();
540
541 overrides.iter().flatten().try_for_each(|s| -> Result<(), eyre::Report> {
542 let (addr, slot, value) = address_slot_value_override(s)?;
543 state_overrides.entry(addr).or_default().insert(slot.into(), value.into());
544 Ok(())
545 })?;
546
547 Ok(state_overrides)
548 };
549
550 for (addr, entries) in parse_state_overrides(&self.state_overrides)? {
552 state_overrides_builder = state_overrides_builder.with_state(addr, entries);
553 }
554
555 for (addr, entries) in parse_state_overrides(&self.state_diff_overrides)? {
557 state_overrides_builder = state_overrides_builder.with_state_diff(addr, entries)
558 }
559
560 Ok(Some(state_overrides_builder.build()))
561 }
562
563 pub fn get_block_overrides(&self) -> eyre::Result<Option<BlockOverrides>> {
565 let mut overrides = BlockOverrides::default();
566 if let Some(number) = self.block_number {
567 overrides = overrides.with_number(U256::from(number));
568 }
569 if let Some(time) = self.block_time {
570 overrides = overrides.with_time(time);
571 }
572 if overrides.is_empty() { Ok(None) } else { Ok(Some(overrides)) }
573 }
574}
575
576impl figment::Provider for CallArgs {
577 fn metadata(&self) -> Metadata {
578 Metadata::named("CallArgs")
579 }
580
581 fn data(&self) -> Result<Map<Profile, Dict>, figment::Error> {
582 let mut map = Map::new();
583
584 if let Some(evm_version) = self.evm_version {
585 map.insert("evm_version".into(), figment::value::Value::serialize(evm_version)?);
586 }
587
588 Ok(Map::from([(Config::selected_profile(), map)]))
589 }
590}
591
592fn address_value_override(address_override: &str) -> Result<(&str, &str)> {
594 address_override.split_once(':').ok_or_else(|| {
595 eyre::eyre!("Invalid override {address_override}. Expected <address>:<value>")
596 })
597}
598
599fn address_slot_value_override(address_override: &str) -> Result<(Address, U256, U256)> {
601 let captures = OVERRIDE_PATTERN.captures(address_override).ok_or_else(|| {
602 eyre::eyre!("Invalid override {address_override}. Expected <address>:<slot>:<value>")
603 })?;
604
605 Ok((
606 captures[1].parse()?, captures[2].parse()?, captures[3].parse()?, ))
610}
611
612#[cfg(test)]
613mod tests {
614 use super::*;
615 use alloy_primitives::{U64, address, b256, fixed_bytes};
616
617 #[test]
618 fn test_get_state_overrides() {
619 let call_args = CallArgs::parse_from([
620 "foundry-cli",
621 "--override-balance",
622 "0x0000000000000000000000000000000000000001:2",
623 "--override-nonce",
624 "0x0000000000000000000000000000000000000001:3",
625 "--override-code",
626 "0x0000000000000000000000000000000000000001:0x04",
627 "--override-state",
628 "0x0000000000000000000000000000000000000001:5:6",
629 "--override-state-diff",
630 "0x0000000000000000000000000000000000000001:7:8",
631 ]);
632 let overrides = call_args.get_state_overrides().unwrap().unwrap();
633 let address = address!("0x0000000000000000000000000000000000000001");
634 if let Some(account_override) = overrides.get(&address) {
635 if let Some(balance) = account_override.balance {
636 assert_eq!(balance, U256::from(2));
637 }
638 if let Some(nonce) = account_override.nonce {
639 assert_eq!(nonce, 3);
640 }
641 if let Some(code) = &account_override.code {
642 assert_eq!(*code, Bytes::from([0x04]));
643 }
644 if let Some(state) = &account_override.state
645 && let Some(value) = state.get(&b256!(
646 "0x0000000000000000000000000000000000000000000000000000000000000005"
647 ))
648 {
649 assert_eq!(
650 *value,
651 b256!("0x0000000000000000000000000000000000000000000000000000000000000006")
652 );
653 }
654 if let Some(state_diff) = &account_override.state_diff
655 && let Some(value) = state_diff.get(&b256!(
656 "0x0000000000000000000000000000000000000000000000000000000000000007"
657 ))
658 {
659 assert_eq!(
660 *value,
661 b256!("0x0000000000000000000000000000000000000000000000000000000000000008")
662 );
663 }
664 }
665 }
666
667 #[test]
668 fn test_get_state_overrides_empty() {
669 let call_args = CallArgs::parse_from([""]);
670 let overrides = call_args.get_state_overrides().unwrap();
671 assert_eq!(overrides, None);
672 }
673
674 #[test]
675 fn test_get_block_overrides() {
676 let mut call_args = CallArgs::parse_from([""]);
677 call_args.block_number = Some(1);
678 call_args.block_time = Some(2);
679 let overrides = call_args.get_block_overrides().unwrap().unwrap();
680 assert_eq!(overrides.number, Some(U256::from(1)));
681 assert_eq!(overrides.time, Some(2));
682 }
683
684 #[test]
685 fn test_get_block_overrides_empty() {
686 let call_args = CallArgs::parse_from([""]);
687 let overrides = call_args.get_block_overrides().unwrap();
688 assert_eq!(overrides, None);
689 }
690
691 #[test]
692 fn test_address_value_override_success() {
693 let text = "0x0000000000000000000000000000000000000001:2";
694 let (address, value) = address_value_override(text).unwrap();
695 assert_eq!(address, "0x0000000000000000000000000000000000000001");
696 assert_eq!(value, "2");
697 }
698
699 #[test]
700 fn test_address_value_override_error() {
701 let text = "invalid_value";
702 let error = address_value_override(text).unwrap_err();
703 assert_eq!(error.to_string(), "Invalid override invalid_value. Expected <address>:<value>");
704 }
705
706 #[test]
707 fn test_address_slot_value_override_success() {
708 let text = "0x0000000000000000000000000000000000000001:2:3";
709 let (address, slot, value) = address_slot_value_override(text).unwrap();
710 assert_eq!(*address, fixed_bytes!("0x0000000000000000000000000000000000000001"));
711 assert_eq!(slot, U256::from(2));
712 assert_eq!(value, U256::from(3));
713 }
714
715 #[test]
716 fn test_address_slot_value_override_error() {
717 let text = "invalid_value";
718 let error = address_slot_value_override(text).unwrap_err();
719 assert_eq!(
720 error.to_string(),
721 "Invalid override invalid_value. Expected <address>:<slot>:<value>"
722 );
723 }
724
725 #[test]
726 fn can_parse_call_data() {
727 let data = hex::encode("hello");
728 let args = CallArgs::parse_from(["foundry-cli", "--data", data.as_str()]);
729 assert_eq!(args.data, Some(data));
730
731 let data = hex::encode_prefixed("hello");
732 let args = CallArgs::parse_from(["foundry-cli", "--data", data.as_str()]);
733 assert_eq!(args.data, Some(data));
734 }
735
736 #[test]
737 fn can_parse_state_overrides() {
738 let args = CallArgs::parse_from([
739 "foundry-cli",
740 "--override-balance",
741 "0x123:0x1234",
742 "--override-nonce",
743 "0x123:1",
744 "--override-code",
745 "0x123:0x1234",
746 "--override-state",
747 "0x123:0x1:0x1234",
748 ]);
749
750 assert_eq!(args.balance_overrides, Some(vec!["0x123:0x1234".to_string()]));
751 assert_eq!(args.nonce_overrides, Some(vec!["0x123:1".to_string()]));
752 assert_eq!(args.code_overrides, Some(vec!["0x123:0x1234".to_string()]));
753 assert_eq!(args.state_overrides, Some(vec!["0x123:0x1:0x1234".to_string()]));
754 }
755
756 #[test]
757 fn can_parse_multiple_state_overrides() {
758 let args = CallArgs::parse_from([
759 "foundry-cli",
760 "--override-balance",
761 "0x123:0x1234",
762 "--override-balance",
763 "0x456:0x5678",
764 "--override-nonce",
765 "0x123:1",
766 "--override-nonce",
767 "0x456:2",
768 "--override-code",
769 "0x123:0x1234",
770 "--override-code",
771 "0x456:0x5678",
772 "--override-state",
773 "0x123:0x1:0x1234",
774 "--override-state",
775 "0x456:0x2:0x5678",
776 ]);
777
778 assert_eq!(
779 args.balance_overrides,
780 Some(vec!["0x123:0x1234".to_string(), "0x456:0x5678".to_string()])
781 );
782 assert_eq!(args.nonce_overrides, Some(vec!["0x123:1".to_string(), "0x456:2".to_string()]));
783 assert_eq!(
784 args.code_overrides,
785 Some(vec!["0x123:0x1234".to_string(), "0x456:0x5678".to_string()])
786 );
787 assert_eq!(
788 args.state_overrides,
789 Some(vec!["0x123:0x1:0x1234".to_string(), "0x456:0x2:0x5678".to_string()])
790 );
791 }
792
793 #[test]
794 fn test_negative_args_with_flags() {
795 let args = CallArgs::parse_from([
797 "foundry-cli",
798 "--trace",
799 "0xDeaDBeeFcAfEbAbEfAcEfEeDcBaDbEeFcAfEbAbE",
800 "process(int256)",
801 "-999999",
802 "--debug",
803 ]);
804
805 assert!(args.trace);
806 assert!(args.debug);
807 assert_eq!(args.args, vec!["-999999"]);
808 }
809
810 #[test]
811 fn test_transaction_opts_with_trace() {
812 let args = CallArgs::parse_from([
814 "foundry-cli",
815 "--trace",
816 "--gas-limit",
817 "1000000",
818 "--gas-price",
819 "20000000000",
820 "--priority-gas-price",
821 "2000000000",
822 "--nonce",
823 "42",
824 "--value",
825 "1000000000000000000", "--blob-gas-price",
827 "10000000000",
828 "0xDeaDBeeFcAfEbAbEfAcEfEeDcBaDbEeFcAfEbAbE",
829 "balanceOf(address)",
830 "0x123456789abcdef123456789abcdef123456789a",
831 ]);
832
833 assert!(args.trace);
834 assert_eq!(args.tx.gas_limit, Some(U256::from(1000000u32)));
835 assert_eq!(args.tx.gas_price, Some(U256::from(20000000000u64)));
836 assert_eq!(args.tx.priority_gas_price, Some(U256::from(2000000000u64)));
837 assert_eq!(args.tx.nonce, Some(U64::from(42)));
838 assert_eq!(args.tx.value, Some(U256::from(1000000000000000000u64)));
839 assert_eq!(args.tx.blob_gas_price, Some(U256::from(10000000000u64)));
840 }
841}