@@ -41,21 +41,28 @@ pub enum CounterExample {
4141
4242#[ derive( Clone , Debug , Serialize , Deserialize ) ]
4343pub struct BaseCounterExample {
44- /// Address which makes the call
44+ /// Address which makes the call.
4545 pub sender : Option < Address > ,
46- /// Address to which to call to
46+ /// Address to which to call to.
4747 pub addr : Option < Address > ,
48- /// The data to provide
48+ /// The data to provide.
4949 pub calldata : Bytes ,
50- /// Contract name if it exists
50+ /// Contract name if it exists.
5151 pub contract_name : Option < String > ,
52- /// Function signature if it exists
52+ /// Function name if it exists.
53+ pub func_name : Option < String > ,
54+ /// Function signature if it exists.
5355 pub signature : Option < String > ,
54- /// Args used to call the function
56+ /// Pretty formatted args used to call the function.
5557 pub args : Option < String > ,
56- /// Traces
58+ /// Unformatted args used to call the function.
59+ pub raw_args : Option < String > ,
60+ /// Counter example traces.
5761 #[ serde( skip) ]
5862 pub traces : Option < SparsedTraceArena > ,
63+ /// Whether to display sequence as solidity.
64+ #[ serde( skip) ]
65+ pub show_solidity : bool ,
5966}
6067
6168impl BaseCounterExample {
@@ -66,6 +73,7 @@ impl BaseCounterExample {
6673 bytes : & Bytes ,
6774 contracts : & ContractsByAddress ,
6875 traces : Option < SparsedTraceArena > ,
76+ show_solidity : bool ,
6977 ) -> Self {
7078 if let Some ( ( name, abi) ) = & contracts. get ( & addr) {
7179 if let Some ( func) = abi. functions ( ) . find ( |f| f. selector ( ) == bytes[ ..4 ] ) {
@@ -76,11 +84,16 @@ impl BaseCounterExample {
7684 addr : Some ( addr) ,
7785 calldata : bytes. clone ( ) ,
7886 contract_name : Some ( name. clone ( ) ) ,
87+ func_name : Some ( func. name . clone ( ) ) ,
7988 signature : Some ( func. signature ( ) ) ,
8089 args : Some (
8190 foundry_common:: fmt:: format_tokens ( & args) . format ( ", " ) . to_string ( ) ,
8291 ) ,
92+ raw_args : Some (
93+ foundry_common:: fmt:: format_tokens_raw ( & args) . format ( ", " ) . to_string ( ) ,
94+ ) ,
8395 traces,
96+ show_solidity,
8497 } ;
8598 }
8699 }
@@ -91,9 +104,12 @@ impl BaseCounterExample {
91104 addr : Some ( addr) ,
92105 calldata : bytes. clone ( ) ,
93106 contract_name : None ,
107+ func_name : None ,
94108 signature : None ,
95109 args : None ,
110+ raw_args : None ,
96111 traces,
112+ show_solidity : false ,
97113 }
98114 }
99115
@@ -108,17 +124,40 @@ impl BaseCounterExample {
108124 addr : None ,
109125 calldata : bytes,
110126 contract_name : None ,
127+ func_name : None ,
111128 signature : None ,
112129 args : Some ( foundry_common:: fmt:: format_tokens ( & args) . format ( ", " ) . to_string ( ) ) ,
130+ raw_args : Some ( foundry_common:: fmt:: format_tokens_raw ( & args) . format ( ", " ) . to_string ( ) ) ,
113131 traces,
132+ show_solidity : false ,
114133 }
115134 }
116135}
117136
118137impl fmt:: Display for BaseCounterExample {
119138 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
139+ // Display counterexample as solidity.
140+ if self . show_solidity {
141+ if let ( Some ( sender) , Some ( contract) , Some ( address) , Some ( func_name) , Some ( args) ) =
142+ ( & self . sender , & self . contract_name , & self . addr , & self . func_name , & self . raw_args )
143+ {
144+ writeln ! ( f, "\t \t vm.prank({sender});" ) ?;
145+ write ! (
146+ f,
147+ "\t \t {}({}).{}({});" ,
148+ contract. split_once( ':' ) . map_or( contract. as_str( ) , |( _, contract) | contract) ,
149+ address,
150+ func_name,
151+ args
152+ ) ?;
153+
154+ return Ok ( ( ) )
155+ }
156+ }
157+
158+ // Regular counterexample display.
120159 if let Some ( sender) = self . sender {
121- write ! ( f, "sender ={sender} addr=" ) ?
160+ write ! ( f, "\t \t sender ={sender} addr=" ) ?
122161 }
123162
124163 if let Some ( name) = & self . contract_name {
0 commit comments