forge_script/
sequence.rs
1use crate::multi_sequence::MultiChainSequence;
2use eyre::Result;
3use forge_script_sequence::{ScriptSequence, TransactionWithMetadata};
4use foundry_cli::utils::Git;
5use foundry_common::fmt::UIfmt;
6use foundry_compilers::ArtifactId;
7use foundry_config::Config;
8use std::{
9 fmt::{Error, Write},
10 path::Path,
11};
12
13fn format_transaction(index: usize, tx: &TransactionWithMetadata) -> Result<String, Error> {
15 let mut output = String::new();
16 writeln!(output, "### Transaction {index} ###")?;
17 writeln!(output, "{}", tx.tx().pretty())?;
18
19 if !tx.opcode.is_any_create() {
21 if let (Some(name), Some(addr)) = (&tx.contract_name, &tx.contract_address) {
22 writeln!(output, "contract: {name}({addr})")?;
23 }
24 }
25
26 if let (Some(func), Some(args)) = (&tx.function, &tx.arguments) {
28 if args.is_empty() {
29 writeln!(output, "data (decoded): {func}()")?;
30 } else {
31 writeln!(output, "data (decoded): {func}(")?;
32 for (i, arg) in args.iter().enumerate() {
33 writeln!(&mut output, " {}{}", arg, if i + 1 < args.len() { "," } else { "" })?;
34 }
35 writeln!(output, ")")?;
36 }
37 }
38
39 writeln!(output)?;
40 Ok(output)
41}
42
43pub fn get_commit_hash(root: &Path) -> Option<String> {
45 Git::new(root).commit_hash(true, "HEAD").ok()
46}
47
48pub enum ScriptSequenceKind {
49 Single(ScriptSequence),
50 Multi(MultiChainSequence),
51}
52
53impl ScriptSequenceKind {
54 pub fn save(&mut self, silent: bool, save_ts: bool) -> Result<()> {
55 match self {
56 Self::Single(sequence) => sequence.save(silent, save_ts),
57 Self::Multi(sequence) => sequence.save(silent, save_ts),
58 }
59 }
60
61 pub fn sequences(&self) -> &[ScriptSequence] {
62 match self {
63 Self::Single(sequence) => std::slice::from_ref(sequence),
64 Self::Multi(sequence) => &sequence.deployments,
65 }
66 }
67
68 pub fn sequences_mut(&mut self) -> &mut [ScriptSequence] {
69 match self {
70 Self::Single(sequence) => std::slice::from_mut(sequence),
71 Self::Multi(sequence) => &mut sequence.deployments,
72 }
73 }
74 pub fn update_paths_to_broadcasted(
76 &mut self,
77 config: &Config,
78 sig: &str,
79 target: &ArtifactId,
80 ) -> Result<()> {
81 match self {
82 Self::Single(sequence) => {
83 sequence.paths =
84 Some(ScriptSequence::get_paths(config, sig, target, sequence.chain, false)?);
85 }
86 Self::Multi(sequence) => {
87 (sequence.path, sequence.sensitive_path) =
88 MultiChainSequence::get_paths(config, sig, target, false)?;
89 }
90 };
91
92 Ok(())
93 }
94
95 pub fn show_transactions(&self) -> Result<()> {
96 for sequence in self.sequences() {
97 if !sequence.transactions.is_empty() {
98 sh_println!("\nChain {}\n", sequence.chain)?;
99
100 for (i, tx) in sequence.transactions.iter().enumerate() {
101 sh_print!("{}", format_transaction(i + 1, tx)?)?;
102 }
103 }
104 }
105
106 Ok(())
107 }
108}
109
110impl Drop for ScriptSequenceKind {
111 fn drop(&mut self) {
112 if let Err(err) = self.save(false, true) {
113 error!(?err, "could not save deployment sequence");
114 }
115 }
116}