@@ -18,7 +18,7 @@ use linera_base::{
1818 Amount , ApplicationDescription , Bytecode , Resources , SendMessageRequest , StreamUpdate ,
1919 } ,
2020 ensure,
21- identifiers:: { Account , AccountOwner , ApplicationId , ChainId , StreamName } ,
21+ identifiers:: { Account , AccountOwner , ApplicationId , ChainId , ModuleId , StreamName } ,
2222 vm:: { EvmInstantiation , EvmOperation , EvmQuery , VmRuntime } ,
2323} ;
2424use revm:: { primitives:: Bytes , InspectCommitEvm , InspectEvm , Inspector } ;
@@ -350,10 +350,6 @@ fn get_precompile_argument<Ctx: ContextTr>(
350350 context : & mut Ctx ,
351351 inputs : & InputsImpl ,
352352) -> Result < Vec < u8 > , ExecutionError > {
353- ensure ! (
354- inputs. call_value == U256 :: ZERO ,
355- EvmExecutionError :: NoTransferInRuntimeCall
356- ) ;
357353 Ok ( get_argument ( context, & inputs. input ) )
358354}
359355
@@ -764,6 +760,24 @@ impl<'a, Runtime: ContractRuntime> Inspector<Ctx<'a, Runtime>>
764760}
765761
766762impl < Runtime : ContractRuntime > CallInterceptorContract < Runtime > {
763+ /// Gets the expected `ApplicationId`.
764+ fn get_expected_application_id ( runtime : & mut Runtime , module_id : ModuleId ) -> Result < ApplicationId , ExecutionError > {
765+ let chain_id = runtime. chain_id ( ) ?;
766+ let block_height = runtime. block_height ( ) ?;
767+ let application_index = runtime. application_index ( ) ?;
768+ let parameters = JSON_EMPTY_VECTOR . to_vec ( ) ; // No constructor
769+ let required_application_ids = Vec :: new ( ) ;
770+ let application_description = ApplicationDescription {
771+ module_id,
772+ creator_chain_id : chain_id,
773+ block_height,
774+ application_index,
775+ parameters : parameters. clone ( ) ,
776+ required_application_ids,
777+ } ;
778+ Ok ( ApplicationId :: from ( & application_description) )
779+ }
780+
767781 /// The function `fn create` of the inspector trait is called
768782 /// when a contract is going to be instantiated. Since the
769783 /// function can have some error case which are not supported
@@ -866,7 +880,10 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
866880 } else {
867881 if inputs. value != U256 :: ZERO {
868882 // decrease the balance of the contract address by the expected amount.
869- // We put the address as
883+ // We put the tokens in FAUCET_ADDRESS because we cannot transfer to
884+ // a contract that do not yet exist.
885+ // It is a common construction. We can see that in ERC20 contract code
886+ // for example for burning and minting.
870887 Self :: revm_transfer (
871888 context,
872889 self . db . contract_address ,
@@ -879,8 +896,6 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
879896 let mut runtime = context. db ( ) . 0 . runtime . lock ( ) . unwrap ( ) ;
880897 let module_id = runtime. publish_module ( contract, service, VmRuntime :: Evm ) ?;
881898 let chain_id = runtime. chain_id ( ) ?;
882- let block_height = runtime. block_height ( ) ?;
883- let application_index = runtime. application_index ( ) ?;
884899 let application_id = runtime. application_id ( ) ?;
885900 let parameters = JSON_EMPTY_VECTOR . to_vec ( ) ; // No constructor
886901 let evm_call = EvmInstantiation {
@@ -889,15 +904,7 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
889904 } ;
890905 let argument = serde_json:: to_vec ( & evm_call) ?;
891906 let required_application_ids = Vec :: new ( ) ;
892- let application_description = ApplicationDescription {
893- module_id,
894- creator_chain_id : chain_id,
895- block_height,
896- application_index,
897- parameters : parameters. clone ( ) ,
898- required_application_ids : Vec :: new ( ) ,
899- } ;
900- let expected_application_id = ApplicationId :: from ( & application_description) ;
907+ let expected_application_id = Self :: get_expected_application_id ( & mut runtime, module_id) ?;
901908 if inputs. value != U256 :: ZERO {
902909 let amount = Amount :: try_from ( inputs. value ) . map_err ( EvmExecutionError :: from) ?;
903910 let destination = Account {
@@ -969,18 +976,20 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
969976 let owner: AccountOwner = inputs. bytecode_address . into ( ) ;
970977 if value != U256 :: ZERO {
971978 // In Linera, only non-zero transfers matter
972- let mut runtime = context
973- . db ( )
974- . 0
975- . runtime
976- . lock ( )
977- . expect ( "The lock should be possible" ) ;
978- let amount = Amount :: try_from ( value) . map_err ( EvmExecutionError :: from) ?;
979- let chain_id = runtime. chain_id ( ) ?;
980- let destination = Account { chain_id, owner } ;
981- runtime. transfer ( source, destination, amount) ?;
979+ {
980+ let mut runtime = context
981+ . db ( )
982+ . 0
983+ . runtime
984+ . lock ( )
985+ . expect ( "The lock should be possible" ) ;
986+ let amount = Amount :: try_from ( value) . map_err ( EvmExecutionError :: from) ?;
987+ let chain_id = runtime. chain_id ( ) ?;
988+ let destination = Account { chain_id, owner } ;
989+ runtime. transfer ( source, destination, amount) ?;
990+ }
991+ Self :: revm_transfer ( context, inputs. caller , inputs. target_address , value) ?;
982992 }
983- Self :: revm_transfer ( context, inputs. caller , inputs. target_address , value) ?;
984993 }
985994 // Other smart contracts calls are handled by the runtime
986995 let target = address_to_user_application_id ( inputs. target_address ) ;
@@ -1027,13 +1036,11 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
10271036 destination : Address ,
10281037 value : U256 ,
10291038 ) -> Result < ( ) , ExecutionError > {
1030- if value != U256 :: ZERO {
1031- // In Ethereum, all transfers matter
1032- if let Some ( error) = context. journal ( ) . transfer ( source, destination, value) ? {
1033- let error = format ! ( "{error:?}" ) ;
1034- let error = EvmExecutionError :: TransactError ( error) ;
1035- return Err ( error. into ( ) ) ;
1036- }
1039+ // In Ethereum, all transfers matter
1040+ if let Some ( error) = context. journal ( ) . transfer ( source, destination, value) ? {
1041+ let error = format ! ( "{error:?}" ) ;
1042+ let error = EvmExecutionError :: TransactError ( error) ;
1043+ return Err ( error. into ( ) ) ;
10371044 }
10381045 Ok ( ( ) )
10391046 }
0 commit comments