@@ -8,7 +8,7 @@ use crate::{
88use itertools:: Itertools ;
99use solar_parse:: interface:: Session ;
1010use solar_sema:: {
11- hir:: { ContractId , Expr , ExprKind , Hir , TypeKind , Visit } ,
11+ hir:: { ContractId , Expr , ExprKind , Hir , NamedArg , TypeKind , Visit } ,
1212 interface:: { data_structures:: Never , source_map:: FileName , SourceMap } ,
1313} ;
1414use std:: {
@@ -95,8 +95,9 @@ impl PreprocessorDependencies {
9595enum BytecodeDependencyKind {
9696 /// `type(Contract).creationCode`
9797 CreationCode ,
98- /// `new Contract`. Holds the name of the contract and args length.
99- New ( String , usize , usize ) ,
98+ /// `new Contract`. Holds the name of the contract, args length and offset, `msg.value` (if
99+ /// any) and salt (if any).
100+ New ( String , usize , usize , Option < String > , Option < String > ) ,
100101}
101102
102103/// Represents a single bytecode dependency.
@@ -193,6 +194,8 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
193194 name. to_string ( ) ,
194195 args_len. to_usize ( ) ,
195196 offset,
197+ named_arg ( self . src , named_args, "value" , self . source_map ) ,
198+ named_arg ( self . src , named_args, "salt" , self . source_map ) ,
196199 ) ,
197200 loc : SourceMapLocation :: from_span ( self . source_map , ty. span ) ,
198201 referenced_contract : contract_id,
@@ -222,6 +225,21 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
222225 }
223226}
224227
228+ /// Helper function to extract value of a given named arg.
229+ fn named_arg (
230+ src : & str ,
231+ named_args : & Option < & [ NamedArg < ' _ > ] > ,
232+ arg : & str ,
233+ source_map : & SourceMap ,
234+ ) -> Option < String > {
235+ named_args. unwrap_or_default ( ) . iter ( ) . find ( |named_arg| named_arg. name . as_str ( ) == arg) . map (
236+ |named_arg| {
237+ let named_arg_loc = SourceMapLocation :: from_span ( source_map, named_arg. value . span ) ;
238+ src[ named_arg_loc. start ..named_arg_loc. end ] . to_string ( )
239+ } ,
240+ )
241+ }
242+
225243/// Goes over all test/script files and replaces bytecode dependencies with cheatcode
226244/// invocations.
227245pub ( crate ) fn remove_bytecode_dependencies (
@@ -260,39 +278,46 @@ pub(crate) fn remove_bytecode_dependencies(
260278 format ! ( "{vm}.getCode(\" {artifact}\" )" ) ,
261279 ) ) ;
262280 }
263- BytecodeDependencyKind :: New ( name, args_length, offset) => {
264- if constructor_data. is_none ( ) {
265- // if there's no constructor, we can just call deployCode with one
266- // argument
267- updates. insert ( (
268- dep. loc . start ,
269- dep. loc . end + args_length,
270- format ! ( "{name}(payable({vm}.deployCode(\" {artifact}\" )))" ) ,
271- ) ) ;
272- } else {
273- // if there's a constructor, we use our helper
281+ BytecodeDependencyKind :: New ( name, args_length, offset, value, salt) => {
282+ let mut update = format ! ( "{name}(payable({vm}.deployCode({{" ) ;
283+ update. push_str ( & format ! ( "_artifact: \" {artifact}\" " ) ) ;
284+
285+ if let Some ( value) = value {
286+ update. push_str ( ", " ) ;
287+ update. push_str ( & format ! ( "_value: {value}" ) ) ;
288+ }
289+
290+ if let Some ( salt) = salt {
291+ update. push_str ( ", " ) ;
292+ update. push_str ( & format ! ( "_salt: {salt}" ) ) ;
293+ }
294+
295+ if constructor_data. is_some ( ) {
296+ // Insert our helper
274297 used_helpers. insert ( dep. referenced_contract ) ;
275- updates. insert ( (
276- dep. loc . start ,
277- dep. loc . end + offset,
278- format ! (
279- "deployCode{id}(DeployHelper{id}.ConstructorArgs" ,
280- id = dep. referenced_contract. get( )
281- ) ,
298+
299+ update. push_str ( ", " ) ;
300+ update. push_str ( & format ! (
301+ "_args: encodeArgs{id}(DeployHelper{id}.ConstructorArgs" ,
302+ id = dep. referenced_contract. get( )
282303 ) ) ;
304+ updates. insert ( ( dep. loc . start , dep. loc . end + offset, update) ) ;
283305 updates. insert ( (
284306 dep. loc . end + args_length,
285307 dep. loc . end + args_length,
286- ")" . to_string ( ) ,
308+ ")}))) " . to_string ( ) ,
287309 ) ) ;
310+ } else {
311+ update. push_str ( "})))" ) ;
312+ updates. insert ( ( dep. loc . start , dep. loc . end + args_length, update) ) ;
288313 }
289314 }
290315 } ;
291316 }
292317 let helper_imports = used_helpers. into_iter ( ) . map ( |id| {
293318 let id = id. get ( ) ;
294319 format ! (
295- "import {{DeployHelper{id}, encodeArgs{id}, deployCode{id} }} from \" foundry-pp/DeployHelper{id}.sol\" ;" ,
320+ "import {{DeployHelper{id}, encodeArgs{id}}} from \" foundry-pp/DeployHelper{id}.sol\" ;" ,
296321 )
297322 } ) . join ( "\n " ) ;
298323 updates. insert ( (
@@ -303,8 +328,14 @@ pub(crate) fn remove_bytecode_dependencies(
303328{helper_imports}
304329
305330interface {vm_interface_name} {{
306- function deployCode(string memory _artifact, bytes memory _data) external returns (address);
307331 function deployCode(string memory _artifact) external returns (address);
332+ function deployCode(string memory _artifact, bytes32 _salt) external returns (address);
333+ function deployCode(string memory _artifact, bytes memory _args) external returns (address);
334+ function deployCode(string memory _artifact, bytes memory _args, bytes32 _salt) external returns (address);
335+ function deployCode(string memory _artifact, uint256 _value) external returns (address);
336+ function deployCode(string memory _artifact, uint256 _value, bytes32 _salt) external returns (address);
337+ function deployCode(string memory _artifact, bytes memory _args, uint256 _value) external returns (address);
338+ function deployCode(string memory _artifact, bytes memory _args, uint256 _value, bytes32 _salt) external returns (address);
308339 function getCode(string memory _artifact) external returns (bytes memory);
309340}}"#
310341 ) ,
0 commit comments