@@ -8,7 +8,7 @@ use crate::{
8
8
use itertools:: Itertools ;
9
9
use solar_parse:: interface:: Session ;
10
10
use solar_sema:: {
11
- hir:: { ContractId , Expr , ExprKind , Hir , TypeKind , Visit } ,
11
+ hir:: { ContractId , Expr , ExprKind , Hir , NamedArg , TypeKind , Visit } ,
12
12
interface:: { data_structures:: Never , source_map:: FileName , SourceMap } ,
13
13
} ;
14
14
use std:: {
@@ -95,8 +95,9 @@ impl PreprocessorDependencies {
95
95
enum BytecodeDependencyKind {
96
96
/// `type(Contract).creationCode`
97
97
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 > ) ,
100
101
}
101
102
102
103
/// Represents a single bytecode dependency.
@@ -193,6 +194,8 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
193
194
name. to_string ( ) ,
194
195
args_len. to_usize ( ) ,
195
196
offset,
197
+ named_arg ( & self . src , named_args, "value" , self . source_map ) ,
198
+ named_arg ( & self . src , named_args, "salt" , self . source_map ) ,
196
199
) ,
197
200
loc : SourceMapLocation :: from_span ( self . source_map , ty. span ) ,
198
201
referenced_contract : contract_id,
@@ -222,6 +225,21 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
222
225
}
223
226
}
224
227
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 ( ) . into_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
+
225
243
/// Goes over all test/script files and replaces bytecode dependencies with cheatcode
226
244
/// invocations.
227
245
pub ( crate ) fn remove_bytecode_dependencies (
@@ -260,39 +278,46 @@ pub(crate) fn remove_bytecode_dependencies(
260
278
format ! ( "{vm}.getCode(\" {artifact}\" )" ) ,
261
279
) ) ;
262
280
}
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
274
297
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( )
282
303
) ) ;
304
+ updates. insert ( ( dep. loc . start , dep. loc . end + offset, update) ) ;
283
305
updates. insert ( (
284
306
dep. loc . end + args_length,
285
307
dep. loc . end + args_length,
286
- ")" . to_string ( ) ,
308
+ ")}))) " . to_string ( ) ,
287
309
) ) ;
310
+ } else {
311
+ update. push_str ( "})))" ) ;
312
+ updates. insert ( ( dep. loc . start , dep. loc . end + args_length, update) ) ;
288
313
}
289
314
}
290
315
} ;
291
316
}
292
317
let helper_imports = used_helpers. into_iter ( ) . map ( |id| {
293
318
let id = id. get ( ) ;
294
319
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\" ;" ,
296
321
)
297
322
} ) . join ( "\n " ) ;
298
323
updates. insert ( (
@@ -303,8 +328,14 @@ pub(crate) fn remove_bytecode_dependencies(
303
328
{helper_imports}
304
329
305
330
interface {vm_interface_name} {{
306
- function deployCode(string memory _artifact, bytes memory _data) external returns (address);
307
331
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);
308
339
function getCode(string memory _artifact) external returns (bytes memory);
309
340
}}"#
310
341
) ,
0 commit comments