@@ -21,8 +21,9 @@ use alloy_sol_types::{SolInterface, SolValue};
2121use foundry_common:: { evm:: Breakpoints , provider:: alloy:: RpcUrl , SELECTOR_LEN } ;
2222use foundry_evm_core:: {
2323 abi:: Vm :: stopExpectSafeMemoryCall,
24- backend:: { DatabaseError , DatabaseExt , RevertDiagnostic } ,
25- constants:: { CHEATCODE_ADDRESS , DEFAULT_CREATE2_DEPLOYER , HARDHAT_CONSOLE_ADDRESS } ,
24+ backend:: { DatabaseExt , RevertDiagnostic } ,
25+ constants:: { CHEATCODE_ADDRESS , HARDHAT_CONSOLE_ADDRESS } ,
26+ InspectorExt ,
2627} ;
2728use itertools:: Itertools ;
2829use revm:: {
@@ -1327,22 +1328,19 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
13271328 ecx. env . tx . caller = broadcast. new_origin ;
13281329
13291330 if ecx. journaled_state . depth ( ) == broadcast. depth {
1330- let ( bytecode, to, nonce) = process_broadcast_create (
1331- broadcast. new_origin ,
1332- call. init_code . clone ( ) ,
1333- ecx,
1334- call,
1335- ) ;
1331+ call. caller = broadcast. new_origin ;
13361332 let is_fixed_gas_limit = check_if_fixed_gas_limit ( ecx, call. gas_limit ) ;
13371333
1334+ let account = & ecx. journaled_state . state ( ) [ & broadcast. new_origin ] ;
1335+
13381336 self . broadcastable_transactions . push_back ( BroadcastableTransaction {
13391337 rpc : ecx. db . active_fork_url ( ) ,
13401338 transaction : TransactionRequest {
13411339 from : Some ( broadcast. new_origin ) ,
1342- to,
1340+ to : None ,
13431341 value : Some ( call. value ) ,
1344- input : TransactionInput :: new ( bytecode ) ,
1345- nonce : Some ( nonce) ,
1342+ input : TransactionInput :: new ( call . init_code . clone ( ) ) ,
1343+ nonce : Some ( account . info . nonce ) ,
13461344 gas : if is_fixed_gas_limit {
13471345 Some ( call. gas_limit as u128 )
13481346 } else {
@@ -1351,6 +1349,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
13511349 ..Default :: default ( )
13521350 } ,
13531351 } ) ;
1352+
13541353 let kind = match call. scheme {
13551354 CreateScheme :: Create => "create" ,
13561355 CreateScheme :: Create2 { .. } => "create2" ,
@@ -1360,29 +1359,6 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
13601359 }
13611360 }
13621361
1363- // Apply the Create2 deployer
1364- if self . broadcast . is_some ( ) || self . config . always_use_create_2_factory {
1365- match apply_create2_deployer (
1366- ecx,
1367- call,
1368- self . prank . as_ref ( ) ,
1369- self . broadcast . as_ref ( ) ,
1370- self . recorded_account_diffs_stack . as_mut ( ) ,
1371- ) {
1372- Ok ( _) => { }
1373- Err ( err) => {
1374- return Some ( CreateOutcome {
1375- result : InterpreterResult {
1376- result : InstructionResult :: Revert ,
1377- output : Error :: encode ( err) ,
1378- gas,
1379- } ,
1380- address : None ,
1381- } )
1382- }
1383- } ;
1384- }
1385-
13861362 // allow cheatcodes from the address of the new contract
13871363 // Compute the address *after* any possible broadcast updates, so it's based on the updated
13881364 // call inputs
@@ -1526,6 +1502,29 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
15261502 }
15271503}
15281504
1505+ impl < DB : DatabaseExt > InspectorExt < DB > for Cheatcodes {
1506+ fn should_use_create2_factory (
1507+ & mut self ,
1508+ ecx : & mut EvmContext < DB > ,
1509+ inputs : & mut CreateInputs ,
1510+ ) -> bool {
1511+ if let CreateScheme :: Create2 { .. } = inputs. scheme {
1512+ let target_depth = if let Some ( prank) = & self . prank {
1513+ prank. depth
1514+ } else if let Some ( broadcast) = & self . broadcast {
1515+ broadcast. depth
1516+ } else {
1517+ 1
1518+ } ;
1519+
1520+ ecx. journaled_state . depth ( ) == target_depth &&
1521+ ( self . broadcast . is_some ( ) || self . config . always_use_create_2_factory )
1522+ } else {
1523+ false
1524+ }
1525+ }
1526+ }
1527+
15291528/// Helper that expands memory, stores a revert string pertaining to a disallowed memory write,
15301529/// and sets the return range to the revert string's location in memory.
15311530///
@@ -1554,110 +1553,6 @@ fn disallowed_mem_write(
15541553 } ;
15551554}
15561555
1557- /// Applies the default CREATE2 deployer for contract creation.
1558- ///
1559- /// This function is invoked during the contract creation process and updates the caller of the
1560- /// contract creation transaction to be the `DEFAULT_CREATE2_DEPLOYER` if the `CreateScheme` is
1561- /// `Create2` and the current execution depth matches the depth at which the `prank` or `broadcast`
1562- /// was started, or the default depth of 1 if no prank or broadcast is currently active.
1563- ///
1564- /// Returns a `DatabaseError::MissingCreate2Deployer` if the `DEFAULT_CREATE2_DEPLOYER` account is
1565- /// not found or if it does not have any associated bytecode.
1566- fn apply_create2_deployer < DB : DatabaseExt > (
1567- ecx : & mut InnerEvmContext < DB > ,
1568- call : & mut CreateInputs ,
1569- prank : Option < & Prank > ,
1570- broadcast : Option < & Broadcast > ,
1571- diffs_stack : Option < & mut Vec < Vec < AccountAccess > > > ,
1572- ) -> Result < ( ) , DB :: Error > {
1573- if let CreateScheme :: Create2 { salt } = call. scheme {
1574- let mut base_depth = 1 ;
1575- if let Some ( prank) = & prank {
1576- base_depth = prank. depth ;
1577- } else if let Some ( broadcast) = & broadcast {
1578- base_depth = broadcast. depth ;
1579- }
1580-
1581- // If the create scheme is Create2 and the depth equals the broadcast/prank/default
1582- // depth, then use the default create2 factory as the deployer
1583- if ecx. journaled_state . depth ( ) == base_depth {
1584- // Record the call to the create2 factory in the state diff
1585- if let Some ( recorded_account_diffs_stack) = diffs_stack {
1586- let calldata = [ & salt. to_be_bytes :: < 32 > ( ) [ ..] , & call. init_code [ ..] ] . concat ( ) ;
1587- recorded_account_diffs_stack. push ( vec ! [ AccountAccess {
1588- chainInfo: crate :: Vm :: ChainInfo {
1589- forkId: ecx. db. active_fork_id( ) . unwrap_or_default( ) ,
1590- chainId: U256 :: from( ecx. env. cfg. chain_id) ,
1591- } ,
1592- accessor: call. caller,
1593- account: DEFAULT_CREATE2_DEPLOYER ,
1594- kind: crate :: Vm :: AccountAccessKind :: Call ,
1595- initialized: true ,
1596- oldBalance: U256 :: ZERO , // updated on create_end
1597- newBalance: U256 :: ZERO , // updated on create_end
1598- value: call. value,
1599- data: calldata. into( ) ,
1600- reverted: false ,
1601- deployedCode: Bytes :: new( ) , // updated on create_end
1602- storageAccesses: vec![ ] , // updated on create_end
1603- depth: ecx. journaled_state. depth( ) ,
1604- } ] )
1605- }
1606-
1607- // Sanity checks for our CREATE2 deployer
1608- // TODO: use ecx.load_account
1609- let info =
1610- & ecx. journaled_state . load_account ( DEFAULT_CREATE2_DEPLOYER , & mut ecx. db ) ?. 0 . info ;
1611- match & info. code {
1612- Some ( code) if code. is_empty ( ) => return Err ( DatabaseError :: MissingCreate2Deployer ) ,
1613- None if ecx. db . code_by_hash ( info. code_hash ) ?. is_empty ( ) => {
1614- return Err ( DatabaseError :: MissingCreate2Deployer )
1615- }
1616- _ => { }
1617- }
1618-
1619- call. caller = DEFAULT_CREATE2_DEPLOYER ;
1620- }
1621- }
1622- Ok ( ( ) )
1623- }
1624-
1625- /// Processes the creation of a new contract when broadcasting, preparing the necessary data for the
1626- /// transaction to deploy the contract.
1627- ///
1628- /// Returns the transaction calldata and the target address.
1629- ///
1630- /// If the CreateScheme is Create, then this function returns the input bytecode without
1631- /// modification and no address since it will be filled in later. If the CreateScheme is Create2,
1632- /// then this function returns the calldata for the call to the create2 deployer which must be the
1633- /// salt and init code concatenated.
1634- fn process_broadcast_create < DB : DatabaseExt > (
1635- broadcast_sender : Address ,
1636- bytecode : Bytes ,
1637- ecx : & mut InnerEvmContext < DB > ,
1638- call : & mut CreateInputs ,
1639- ) -> ( Bytes , Option < Address > , u64 ) {
1640- call. caller = broadcast_sender;
1641- match call. scheme {
1642- CreateScheme :: Create => {
1643- ( bytecode, None , ecx. journaled_state . account ( broadcast_sender) . info . nonce )
1644- }
1645- CreateScheme :: Create2 { salt } => {
1646- // We have to increment the nonce of the user address, since this create2 will be done
1647- // by the create2_deployer
1648- let account = ecx. journaled_state . state ( ) . get_mut ( & broadcast_sender) . unwrap ( ) ;
1649- let prev = account. info . nonce ;
1650- // Touch account to ensure that incremented nonce is committed
1651- account. mark_touch ( ) ;
1652- account. info . nonce += 1 ;
1653- debug ! ( target: "cheatcodes" , address=%broadcast_sender, nonce=prev+1 , prev, "incremented nonce in create2" ) ;
1654- // Proxy deployer requires the data to be `salt ++ init_code`
1655- let calldata = [ & salt. to_be_bytes :: < 32 > ( ) [ ..] , & bytecode[ ..] ] . concat ( ) ;
1656- ( calldata. into ( ) , Some ( DEFAULT_CREATE2_DEPLOYER ) , prev)
1657- }
1658- }
1659- }
1660-
16611556// Determines if the gas limit on a given call was manually set in the script and should therefore
16621557// not be overwritten by later estimations
16631558fn check_if_fixed_gas_limit < DB : DatabaseExt > (
0 commit comments