@@ -29,7 +29,7 @@ use alloc::{collections::btree_map::BTreeMap, vec, vec::Vec};
2929use core:: { cell:: RefCell , marker:: PhantomData , ops:: RangeInclusive } ;
3030use fp_evm:: {
3131 ExitError , IsPrecompileResult , Precompile , PrecompileFailure , PrecompileHandle ,
32- PrecompileResult , PrecompileSet ,
32+ PrecompileResult , PrecompileSet , ACCOUNT_CODES_METADATA_PROOF_SIZE ,
3333} ;
3434use frame_support:: pallet_prelude:: Get ;
3535use impl_trait_for_tuples:: impl_for_tuples;
@@ -304,13 +304,11 @@ impl<T: SelectorFilter> PrecompileChecks for CallableByPrecompile<T> {
304304#[ derive( PartialEq ) ]
305305#[ cfg_attr( feature = "std" , derive( Debug ) ) ]
306306pub enum AddressType {
307- /// The code stored at the address is less than 5 bytes, but not well known.
308- Unknown ,
309307 /// No code is stored at the address, therefore is EOA.
310308 EOA ,
311309 /// The 5-byte magic constant for a precompile is stored at the address.
312310 Precompile ,
313- /// The code is greater than 5-bytes, potentially a Smart Contract.
311+ /// Every address that is not a EOA or a Precompile is potentially a Smart Contract.
314312 Contract ,
315313}
316314
@@ -319,39 +317,27 @@ pub fn get_address_type<R: pallet_evm::Config>(
319317 handle : & mut impl PrecompileHandle ,
320318 address : H160 ,
321319) -> Result < AddressType , ExitError > {
320+ // Check if address is a precompile
321+ if let Ok ( true ) = is_precompile_or_fail :: < R > ( address, handle. remaining_gas ( ) ) {
322+ return Ok ( AddressType :: Precompile ) ;
323+ }
324+
325+ // Contracts under-construction don't have code yet
326+ if handle. is_contract_being_constructed ( address) {
327+ return Ok ( AddressType :: Contract ) ;
328+ }
329+
322330 // AccountCodesMetadata:
323331 // Blake2128(16) + H160(20) + CodeMetadata(40)
324- handle. record_db_read :: < R > ( 76 ) ?;
332+ handle. record_db_read :: < R > ( ACCOUNT_CODES_METADATA_PROOF_SIZE as usize ) ?;
325333 let code_len = pallet_evm:: Pallet :: < R > :: account_code_metadata ( address) . size ;
326334
327- // 0 => either EOA or precompile without dummy code
335+ // Having no code at this point means that the address is an EOA
328336 if code_len == 0 {
329337 return Ok ( AddressType :: EOA ) ;
330338 }
331339
332- // dummy code is 5 bytes long, so any other len means it is a contract.
333- if code_len != 5 {
334- return Ok ( AddressType :: Contract ) ;
335- }
336-
337- // check code matches dummy code
338- handle. record_db_read :: < R > ( code_len as usize ) ?;
339- let code = pallet_evm:: AccountCodes :: < R > :: get ( address) ;
340- if code == [ 0x60 , 0x00 , 0x60 , 0x00 , 0xfd ] {
341- return Ok ( AddressType :: Precompile ) ;
342- }
343-
344- Ok ( AddressType :: Unknown )
345- }
346-
347- fn is_address_eoa_or_precompile < R : pallet_evm:: Config > (
348- handle : & mut impl PrecompileHandle ,
349- address : H160 ,
350- ) -> Result < bool , ExitError > {
351- match get_address_type :: < R > ( handle, address) ? {
352- AddressType :: EOA | AddressType :: Precompile => Ok ( true ) ,
353- _ => Ok ( false ) ,
354- }
340+ Ok ( AddressType :: Contract )
355341}
356342
357343/// Common checks for precompile and precompile sets.
@@ -375,17 +361,27 @@ fn common_checks<R: pallet_evm::Config, C: PrecompileChecks>(
375361 u32:: from_be_bytes ( buffer)
376362 } ) ;
377363
378- // Is this selector callable from a smart contract?
379- let callable_by_smart_contract =
380- C :: callable_by_smart_contract ( caller, selector) . unwrap_or ( false ) ;
381- if !callable_by_smart_contract && !is_address_eoa_or_precompile :: < R > ( handle, caller) ? {
382- return Err ( revert ( "Function not callable by smart contracts" ) ) ;
383- }
384-
385- // Is this selector callable from a precompile?
386- let callable_by_precompile = C :: callable_by_precompile ( caller, selector) . unwrap_or ( false ) ;
387- if !callable_by_precompile && is_precompile_or_fail :: < R > ( caller, handle. remaining_gas ( ) ) ? {
388- return Err ( revert ( "Function not callable by precompiles" ) ) ;
364+ let caller_address_type = get_address_type :: < R > ( handle, caller) ?;
365+ match caller_address_type {
366+ AddressType :: Precompile => {
367+ // Is this selector callable from a precompile?
368+ let callable_by_precompile =
369+ C :: callable_by_precompile ( caller, selector) . unwrap_or ( false ) ;
370+ if !callable_by_precompile {
371+ return Err ( revert ( "Function not callable by precompiles" ) ) ;
372+ }
373+ }
374+ AddressType :: Contract => {
375+ // Is this selector callable from a smart contract?
376+ let callable_by_smart_contract =
377+ C :: callable_by_smart_contract ( caller, selector) . unwrap_or ( false ) ;
378+ if !callable_by_smart_contract {
379+ return Err ( revert ( "Function not callable by smart contracts" ) ) ;
380+ }
381+ }
382+ AddressType :: EOA => {
383+ // No check required for EOA
384+ }
389385 }
390386
391387 Ok ( ( ) )
@@ -463,6 +459,10 @@ impl<'a, H: PrecompileHandle> PrecompileHandle for RestrictiveHandle<'a, H> {
463459 self . handle . context ( )
464460 }
465461
462+ fn origin ( & self ) -> H160 {
463+ self . handle . origin ( )
464+ }
465+
466466 fn is_static ( & self ) -> bool {
467467 self . handle . is_static ( )
468468 }
@@ -484,6 +484,10 @@ impl<'a, H: PrecompileHandle> PrecompileHandle for RestrictiveHandle<'a, H> {
484484 fn refund_external_cost ( & mut self , ref_time : Option < u64 > , proof_size : Option < u64 > ) {
485485 self . handle . refund_external_cost ( ref_time, proof_size)
486486 }
487+
488+ fn is_contract_being_constructed ( & self , address : H160 ) -> bool {
489+ self . handle . is_contract_being_constructed ( address)
490+ }
487491}
488492
489493/// Allows to know if a precompile is active or not.
0 commit comments