linera_execution/evm/
revm.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Code specific to the usage of the [Revm](https://bluealloy.github.io/revm/) runtime.
5
6use core::ops::Range;
7use std::{
8    collections::BTreeSet,
9    convert::TryFrom,
10    sync::{Arc, Mutex},
11};
12
13#[cfg(with_metrics)]
14use linera_base::prometheus_util::MeasureLatency as _;
15use linera_base::{
16    crypto::CryptoHash,
17    data_types::{
18        Amount, ApplicationDescription, Bytecode, Resources, SendMessageRequest, StreamUpdate,
19    },
20    ensure,
21    identifiers::{Account, AccountOwner, ApplicationId, ChainId, ModuleId, StreamName},
22    vm::{EvmInstantiation, EvmOperation, EvmQuery, VmRuntime},
23};
24use revm::{primitives::Bytes, InspectCommitEvm, InspectEvm, Inspector};
25use revm_context::{
26    result::{ExecutionResult, Output, SuccessReason},
27    BlockEnv, Cfg, ContextTr, Evm, Journal, JournalTr, LocalContextTr as _, TxEnv,
28};
29use revm_database::WrapDatabaseRef;
30use revm_handler::{
31    instructions::EthInstructions, EthPrecompiles, MainnetContext, PrecompileProvider,
32};
33use revm_interpreter::{
34    CallInput, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome, CreateScheme, Gas,
35    InputsImpl, InstructionResult, InterpreterResult,
36};
37use revm_primitives::{hardfork::SpecId, Address, Log, TxKind, U256};
38use revm_state::EvmState;
39use serde::{Deserialize, Serialize};
40
41use crate::{
42    evm::{
43        data_types::AmountU256,
44        database::{DatabaseRuntime, StorageStats, EVM_SERVICE_GAS_LIMIT},
45        inputs::{
46            ensure_message_length, ensure_selector_presence, forbid_execute_operation_origin,
47            get_revm_execute_message_bytes, get_revm_instantiation_bytes,
48            get_revm_process_streams_bytes, has_selector, EXECUTE_MESSAGE_SELECTOR, FAUCET_ADDRESS,
49            INSTANTIATE_SELECTOR, PRECOMPILE_ADDRESS, PROCESS_STREAMS_SELECTOR, SERVICE_ADDRESS,
50            ZERO_ADDRESS,
51        },
52    },
53    BaseRuntime, ContractRuntime, ContractSyncRuntimeHandle, DataBlobHash, EvmExecutionError,
54    EvmRuntime, ExecutionError, ServiceRuntime, ServiceSyncRuntimeHandle, UserContract,
55    UserContractInstance, UserContractModule, UserService, UserServiceInstance, UserServiceModule,
56};
57
58/// The selector when calling for `InterpreterResult`. This is a fictional
59/// selector that does not correspond to a real function.
60const INTERPRETER_RESULT_SELECTOR: &[u8] = &[1, 2, 3, 4];
61
62/// The selector when accessing for the deployed bytecode. This is a fictional
63/// selector that does not correspond to a real function.
64const GET_DEPLOYED_BYTECODE_SELECTOR: &[u8] = &[21, 34, 55, 89];
65
66/// The json serialization of a trivial vector.
67const JSON_EMPTY_VECTOR: &[u8] = &[91, 93];
68
69#[cfg(with_metrics)]
70mod metrics {
71    use std::sync::LazyLock;
72
73    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
74    use prometheus::HistogramVec;
75
76    pub static CONTRACT_INSTANTIATION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
77        register_histogram_vec(
78            "evm_contract_instantiation_latency",
79            "EVM contract instantiation latency",
80            &[],
81            exponential_bucket_latencies(1.0),
82        )
83    });
84
85    pub static SERVICE_INSTANTIATION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
86        register_histogram_vec(
87            "evm_service_instantiation_latency",
88            "EVM service instantiation latency",
89            &[],
90            exponential_bucket_latencies(1.0),
91        )
92    });
93}
94
95#[derive(Clone)]
96pub enum EvmContractModule {
97    #[cfg(with_revm)]
98    Revm { module: Vec<u8> },
99}
100
101impl EvmContractModule {
102    /// Creates a new [`EvmContractModule`] using the EVM module with the provided `contract_bytecode`.
103    pub fn new(
104        contract_bytecode: Bytecode,
105        runtime: EvmRuntime,
106    ) -> Result<Self, EvmExecutionError> {
107        match runtime {
108            #[cfg(with_revm)]
109            EvmRuntime::Revm => Self::from_revm(contract_bytecode),
110        }
111    }
112
113    /// Creates a new [`EvmContractModule`] using the EVM module in `contract_bytecode_file`.
114    #[cfg(with_fs)]
115    pub fn from_file(
116        contract_bytecode_file: impl AsRef<std::path::Path>,
117        runtime: EvmRuntime,
118    ) -> Result<Self, EvmExecutionError> {
119        Self::new(
120            Bytecode::load_from_file(contract_bytecode_file)
121                .map_err(anyhow::Error::from)
122                .map_err(EvmExecutionError::LoadContractModule)?,
123            runtime,
124        )
125    }
126
127    /// Creates a new [`EvmContractModule`] using Revm with the provided bytecode files.
128    pub fn from_revm(contract_bytecode: Bytecode) -> Result<Self, EvmExecutionError> {
129        let module = contract_bytecode.bytes;
130        Ok(EvmContractModule::Revm { module })
131    }
132}
133
134impl UserContractModule for EvmContractModule {
135    fn instantiate(
136        &self,
137        runtime: ContractSyncRuntimeHandle,
138    ) -> Result<UserContractInstance, ExecutionError> {
139        #[cfg(with_metrics)]
140        let _instantiation_latency = metrics::CONTRACT_INSTANTIATION_LATENCY.measure_latency();
141
142        let instance: UserContractInstance = match self {
143            #[cfg(with_revm)]
144            EvmContractModule::Revm { module } => {
145                Box::new(RevmContractInstance::prepare(module.to_vec(), runtime))
146            }
147        };
148
149        Ok(instance)
150    }
151}
152
153/// A user service in a compiled EVM module.
154#[derive(Clone)]
155pub enum EvmServiceModule {
156    #[cfg(with_revm)]
157    Revm { module: Vec<u8> },
158}
159
160impl EvmServiceModule {
161    /// Creates a new [`EvmServiceModule`] using the EVM module with the provided bytecode.
162    pub fn new(service_bytecode: Bytecode, runtime: EvmRuntime) -> Result<Self, EvmExecutionError> {
163        match runtime {
164            #[cfg(with_revm)]
165            EvmRuntime::Revm => Self::from_revm(service_bytecode),
166        }
167    }
168
169    /// Creates a new [`EvmServiceModule`] using the EVM module in `service_bytecode_file`.
170    #[cfg(with_fs)]
171    pub fn from_file(
172        service_bytecode_file: impl AsRef<std::path::Path>,
173        runtime: EvmRuntime,
174    ) -> Result<Self, EvmExecutionError> {
175        Self::new(
176            Bytecode::load_from_file(service_bytecode_file)
177                .map_err(anyhow::Error::from)
178                .map_err(EvmExecutionError::LoadServiceModule)?,
179            runtime,
180        )
181    }
182
183    /// Creates a new [`EvmServiceModule`] using Revm with the provided bytecode files.
184    pub fn from_revm(contract_bytecode: Bytecode) -> Result<Self, EvmExecutionError> {
185        let module = contract_bytecode.bytes;
186        Ok(EvmServiceModule::Revm { module })
187    }
188}
189
190impl UserServiceModule for EvmServiceModule {
191    fn instantiate(
192        &self,
193        runtime: ServiceSyncRuntimeHandle,
194    ) -> Result<UserServiceInstance, ExecutionError> {
195        #[cfg(with_metrics)]
196        let _instantiation_latency = metrics::SERVICE_INSTANTIATION_LATENCY.measure_latency();
197
198        let instance: UserServiceInstance = match self {
199            #[cfg(with_revm)]
200            EvmServiceModule::Revm { module } => {
201                Box::new(RevmServiceInstance::prepare(module.to_vec(), runtime))
202            }
203        };
204
205        Ok(instance)
206    }
207}
208
209type Ctx<'a, Runtime> = MainnetContext<WrapDatabaseRef<&'a mut DatabaseRuntime<Runtime>>>;
210
211fn address_to_user_application_id(address: Address) -> ApplicationId {
212    let mut vec = vec![0_u8; 32];
213    vec[..20].copy_from_slice(address.as_ref());
214    ApplicationId::new(CryptoHash::try_from(&vec as &[u8]).unwrap())
215}
216
217/// Some functionalities from the BaseRuntime
218#[derive(Debug, Serialize, Deserialize)]
219enum BaseRuntimePrecompile {
220    /// Calling `chain_id` of `BaseRuntime`
221    ChainId,
222    /// Calling `block_height_id` of `BaseRuntime`
223    BlockHeight,
224    /// Calling `application_creator_chain_id` of `BaseRuntime`
225    ApplicationCreatorChainId,
226    /// Calling `read_system_timestamp` of `BaseRuntime`
227    ReadSystemTimestamp,
228    /// Calling `read_chain_balance` of `BaseRuntime`
229    ReadChainBalance,
230    /// Calling `read_owner_balance` of `BaseRuntime`
231    ReadOwnerBalance(AccountOwner),
232    /// Calling `read_owner_balances` of `BaseRuntime`
233    ReadOwnerBalances,
234    /// Calling `read_balance_owners` of `BaseRuntime`
235    ReadBalanceOwners,
236    /// Calling `chain_ownership` of `BaseRuntime`
237    ChainOwnership,
238    /// Calling `read_data_blob` of `BaseRuntime`
239    ReadDataBlob(DataBlobHash),
240    /// Calling `assert_data_blob_exists` of `BaseRuntime`
241    AssertDataBlobExists(DataBlobHash),
242}
243
244/// Some functionalities from the ContractRuntime not in BaseRuntime
245#[derive(Debug, Serialize, Deserialize)]
246enum ContractRuntimePrecompile {
247    /// Calling `authenticated_owner` of `ContractRuntime`
248    AuthenticatedOwner,
249    /// Calling `message_origin_chain_id` of `ContractRuntime`
250    MessageOriginChainId,
251    /// Calling `message_is_bouncing` of `ContractRuntime`
252    MessageIsBouncing,
253    /// Calling `authenticated_caller_id` of `ContractRuntime`
254    AuthenticatedCallerId,
255    /// Calling `send_message` of `ContractRuntime`
256    SendMessage {
257        destination: ChainId,
258        message: Vec<u8>,
259    },
260    /// Calling `try_call_application` of `ContractRuntime`
261    TryCallApplication {
262        target: ApplicationId,
263        argument: Vec<u8>,
264    },
265    /// Calling `emit` of `ContractRuntime`
266    Emit {
267        stream_name: StreamName,
268        value: Vec<u8>,
269    },
270    /// Calling `read_event` of `ContractRuntime`
271    ReadEvent {
272        chain_id: ChainId,
273        stream_name: StreamName,
274        index: u32,
275    },
276    /// Calling `subscribe_to_events` of `ContractRuntime`
277    SubscribeToEvents {
278        chain_id: ChainId,
279        application_id: ApplicationId,
280        stream_name: StreamName,
281    },
282    /// Calling `unsubscribe_from_events` of `ContractRuntime`
283    UnsubscribeFromEvents {
284        chain_id: ChainId,
285        application_id: ApplicationId,
286        stream_name: StreamName,
287    },
288    /// Calling `query_service` of `ContractRuntime`
289    QueryService {
290        application_id: ApplicationId,
291        query: Vec<u8>,
292    },
293    /// Calling `validation_round` of `ContractRuntime`
294    ValidationRound,
295    /// Calling `transfer` of `ContractRuntime`
296    Transfer {
297        account: Account,
298        amount: AmountU256,
299    },
300}
301
302/// Some functionalities from the ServiceRuntime not in BaseRuntime
303#[derive(Debug, Serialize, Deserialize)]
304enum ServiceRuntimePrecompile {
305    /// Calling `try_query_application` of `ServiceRuntime`
306    TryQueryApplication {
307        target: ApplicationId,
308        argument: Vec<u8>,
309    },
310}
311
312/// Key prefixes used to transmit precompiles.
313#[derive(Debug, Serialize, Deserialize)]
314enum RuntimePrecompile {
315    Base(BaseRuntimePrecompile),
316    Contract(ContractRuntimePrecompile),
317    Service(ServiceRuntimePrecompile),
318}
319
320fn get_precompile_output(output: Vec<u8>, gas_limit: u64) -> InterpreterResult {
321    // The gas usage is set to `gas_limit` and no spending is being done on it.
322    // This means that for Revm, it looks like the precompile call costs nothing.
323    // This is because the costs of the EVM precompile calls is accounted for
324    // separately in Linera.
325    let output = Bytes::from(output);
326    let result = InstructionResult::default();
327    let gas = Gas::new(gas_limit);
328    InterpreterResult {
329        result,
330        output,
331        gas,
332    }
333}
334
335fn get_argument<Ctx: ContextTr>(context: &mut Ctx, input: &CallInput) -> Vec<u8> {
336    match input {
337        CallInput::Bytes(bytes) => bytes.to_vec(),
338        CallInput::SharedBuffer(range) => {
339            match context.local().shared_memory_buffer_slice(range.clone()) {
340                None => Vec::new(),
341                Some(slice) => slice.to_vec(),
342            }
343        }
344    }
345}
346
347fn get_value(call_value: &CallValue) -> Result<U256, EvmExecutionError> {
348    match call_value {
349        CallValue::Transfer(value) => Ok(*value),
350        CallValue::Apparent(_) => Err(EvmExecutionError::NoDelegateCall),
351    }
352}
353
354fn get_precompile_argument<Ctx: ContextTr>(
355    context: &mut Ctx,
356    inputs: &InputsImpl,
357) -> Result<Vec<u8>, ExecutionError> {
358    Ok(get_argument(context, &inputs.input))
359}
360
361fn get_call_service_argument<Ctx: ContextTr>(
362    context: &mut Ctx,
363    inputs: &CallInputs,
364) -> Result<Vec<u8>, ExecutionError> {
365    ensure!(
366        get_value(&inputs.value)? == U256::ZERO,
367        EvmExecutionError::NoTransferInServices
368    );
369    let mut argument = INTERPRETER_RESULT_SELECTOR.to_vec();
370    argument.extend(&get_argument(context, &inputs.input));
371    Ok(argument)
372}
373
374fn get_call_contract_argument<Ctx: ContextTr>(
375    context: &mut Ctx,
376    inputs: &CallInputs,
377) -> Result<(Vec<u8>, usize), ExecutionError> {
378    let mut final_argument = INTERPRETER_RESULT_SELECTOR.to_vec();
379    let value = get_value(&inputs.value)?;
380    let argument = get_argument(context, &inputs.input);
381    let n_input = argument.len();
382    let evm_operation = EvmOperation { value, argument };
383    let argument = bcs::to_bytes(&evm_operation)?;
384    final_argument.extend(&argument);
385    Ok((final_argument, n_input))
386}
387
388fn base_runtime_call<Runtime: BaseRuntime>(
389    request: BaseRuntimePrecompile,
390    context: &mut Ctx<'_, Runtime>,
391) -> Result<Vec<u8>, ExecutionError> {
392    let mut runtime = context.db().0.runtime.lock().unwrap();
393    match request {
394        BaseRuntimePrecompile::ChainId => {
395            let chain_id = runtime.chain_id()?;
396            Ok(bcs::to_bytes(&chain_id)?)
397        }
398        BaseRuntimePrecompile::BlockHeight => {
399            let block_height = runtime.block_height()?;
400            Ok(bcs::to_bytes(&block_height)?)
401        }
402        BaseRuntimePrecompile::ApplicationCreatorChainId => {
403            let chain_id = runtime.application_creator_chain_id()?;
404            Ok(bcs::to_bytes(&chain_id)?)
405        }
406        BaseRuntimePrecompile::ReadSystemTimestamp => {
407            let timestamp = runtime.read_system_timestamp()?;
408            Ok(bcs::to_bytes(&timestamp)?)
409        }
410        BaseRuntimePrecompile::ReadChainBalance => {
411            let balance: linera_base::data_types::Amount = runtime.read_chain_balance()?;
412            let balance: AmountU256 = balance.into();
413            Ok(bcs::to_bytes(&balance)?)
414        }
415        BaseRuntimePrecompile::ReadOwnerBalance(account_owner) => {
416            let balance = runtime.read_owner_balance(account_owner)?;
417            let balance = Into::<U256>::into(balance);
418            Ok(bcs::to_bytes(&balance)?)
419        }
420        BaseRuntimePrecompile::ReadOwnerBalances => {
421            let owner_balances = runtime.read_owner_balances()?;
422            let owner_balances = owner_balances
423                .into_iter()
424                .map(|(account_owner, balance)| (account_owner, balance.into()))
425                .collect::<Vec<(AccountOwner, AmountU256)>>();
426            Ok(bcs::to_bytes(&owner_balances)?)
427        }
428        BaseRuntimePrecompile::ReadBalanceOwners => {
429            let owners = runtime.read_balance_owners()?;
430            Ok(bcs::to_bytes(&owners)?)
431        }
432        BaseRuntimePrecompile::ChainOwnership => {
433            let chain_ownership = runtime.chain_ownership()?;
434            Ok(bcs::to_bytes(&chain_ownership)?)
435        }
436        BaseRuntimePrecompile::ReadDataBlob(hash) => runtime.read_data_blob(hash),
437        BaseRuntimePrecompile::AssertDataBlobExists(hash) => {
438            runtime.assert_data_blob_exists(hash)?;
439            Ok(Vec::new())
440        }
441    }
442}
443
444fn precompile_addresses() -> BTreeSet<Address> {
445    let mut addresses = BTreeSet::new();
446    for address in EthPrecompiles::default().warm_addresses() {
447        addresses.insert(address);
448    }
449    addresses.insert(PRECOMPILE_ADDRESS);
450    addresses
451}
452
453#[derive(Debug, Default)]
454struct ContractPrecompile {
455    inner: EthPrecompiles,
456}
457
458impl<'a, Runtime: ContractRuntime> PrecompileProvider<Ctx<'a, Runtime>> for ContractPrecompile {
459    type Output = InterpreterResult;
460
461    fn set_spec(&mut self, spec: <<Ctx<'a, Runtime> as ContextTr>::Cfg as Cfg>::Spec) -> bool {
462        <EthPrecompiles as PrecompileProvider<Ctx<'a, Runtime>>>::set_spec(&mut self.inner, spec)
463    }
464
465    fn run(
466        &mut self,
467        context: &mut Ctx<'a, Runtime>,
468        address: &Address,
469        inputs: &InputsImpl,
470        is_static: bool,
471        gas_limit: u64,
472    ) -> Result<Option<InterpreterResult>, String> {
473        if address == &PRECOMPILE_ADDRESS {
474            let output = Self::call_or_fail(inputs, context)
475                .map_err(|error| format!("ContractPrecompile error: {error}"))?;
476            return Ok(Some(get_precompile_output(output, gas_limit)));
477        }
478        self.inner
479            .run(context, address, inputs, is_static, gas_limit)
480    }
481
482    fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
483        let mut addresses = self.inner.warm_addresses().collect::<Vec<Address>>();
484        addresses.push(PRECOMPILE_ADDRESS);
485        Box::new(addresses.into_iter())
486    }
487
488    fn contains(&self, address: &Address) -> bool {
489        address == &PRECOMPILE_ADDRESS || self.inner.contains(address)
490    }
491}
492
493fn get_evm_destination<Runtime: ContractRuntime>(
494    context: &mut Ctx<'_, Runtime>,
495    account: Account,
496) -> Result<Option<Address>, ExecutionError> {
497    let mut runtime = context.db().0.runtime.lock().unwrap();
498    if runtime.chain_id()? != account.chain_id {
499        return Ok(None);
500    }
501    Ok(account.owner.to_evm_address())
502}
503
504/// We are doing transfers of value from a source to a destination.
505fn revm_transfer<Runtime: ContractRuntime>(
506    context: &mut Ctx<'_, Runtime>,
507    source: Address,
508    destination: Address,
509    value: U256,
510) -> Result<(), ExecutionError> {
511    if let Some(error) = context.journal().transfer(source, destination, value)? {
512        let error = format!("{error:?}");
513        let error = EvmExecutionError::TransactError(error);
514        return Err(error.into());
515    }
516    Ok(())
517}
518
519impl<'a> ContractPrecompile {
520    fn contract_runtime_call<Runtime: ContractRuntime>(
521        request: ContractRuntimePrecompile,
522        context: &mut Ctx<'a, Runtime>,
523    ) -> Result<Vec<u8>, ExecutionError> {
524        match request {
525            ContractRuntimePrecompile::AuthenticatedOwner => {
526                let mut runtime = context.db().0.runtime.lock().unwrap();
527                let account_owner = runtime.authenticated_owner()?;
528                Ok(bcs::to_bytes(&account_owner)?)
529            }
530
531            ContractRuntimePrecompile::MessageOriginChainId => {
532                let mut runtime = context.db().0.runtime.lock().unwrap();
533                let origin_chain_id = runtime.message_origin_chain_id()?;
534                Ok(bcs::to_bytes(&origin_chain_id)?)
535            }
536
537            ContractRuntimePrecompile::MessageIsBouncing => {
538                let mut runtime = context.db().0.runtime.lock().unwrap();
539                let result = runtime.message_is_bouncing()?;
540                Ok(bcs::to_bytes(&result)?)
541            }
542            ContractRuntimePrecompile::AuthenticatedCallerId => {
543                let mut runtime = context.db().0.runtime.lock().unwrap();
544                let application_id = runtime.authenticated_caller_id()?;
545                Ok(bcs::to_bytes(&application_id)?)
546            }
547            ContractRuntimePrecompile::SendMessage {
548                destination,
549                message,
550            } => {
551                let authenticated = true;
552                let is_tracked = true;
553                let grant = Resources::default();
554                let send_message_request = SendMessageRequest {
555                    destination,
556                    authenticated,
557                    is_tracked,
558                    grant,
559                    message,
560                };
561                let mut runtime = context.db().0.runtime.lock().unwrap();
562                runtime.send_message(send_message_request)?;
563                Ok(vec![])
564            }
565            ContractRuntimePrecompile::TryCallApplication { target, argument } => {
566                let authenticated = true;
567                let mut runtime = context.db().0.runtime.lock().unwrap();
568                ensure!(
569                    target != runtime.application_id()?,
570                    EvmExecutionError::NoSelfCall
571                );
572                runtime.try_call_application(authenticated, target, argument)
573            }
574            ContractRuntimePrecompile::Emit { stream_name, value } => {
575                let mut runtime = context.db().0.runtime.lock().unwrap();
576                let result = runtime.emit(stream_name, value)?;
577                Ok(bcs::to_bytes(&result)?)
578            }
579            ContractRuntimePrecompile::ReadEvent {
580                chain_id,
581                stream_name,
582                index,
583            } => {
584                let mut runtime = context.db().0.runtime.lock().unwrap();
585                runtime.read_event(chain_id, stream_name, index)
586            }
587            ContractRuntimePrecompile::SubscribeToEvents {
588                chain_id,
589                application_id,
590                stream_name,
591            } => {
592                let mut runtime = context.db().0.runtime.lock().unwrap();
593                runtime.subscribe_to_events(chain_id, application_id, stream_name)?;
594                Ok(vec![])
595            }
596            ContractRuntimePrecompile::UnsubscribeFromEvents {
597                chain_id,
598                application_id,
599                stream_name,
600            } => {
601                let mut runtime = context.db().0.runtime.lock().unwrap();
602                runtime.unsubscribe_from_events(chain_id, application_id, stream_name)?;
603                Ok(vec![])
604            }
605            ContractRuntimePrecompile::QueryService {
606                application_id,
607                query,
608            } => {
609                let mut runtime = context.db().0.runtime.lock().unwrap();
610                ensure!(
611                    application_id != runtime.application_id()?,
612                    EvmExecutionError::NoSelfCall
613                );
614                runtime.query_service(application_id, query)
615            }
616            ContractRuntimePrecompile::ValidationRound => {
617                let mut runtime = context.db().0.runtime.lock().unwrap();
618                let value = runtime.validation_round()?;
619                Ok(bcs::to_bytes(&value)?)
620            }
621            ContractRuntimePrecompile::Transfer { account, amount } => {
622                if amount.0 != U256::ZERO {
623                    let destination = {
624                        let destination = get_evm_destination(context, account)?;
625                        destination.unwrap_or(FAUCET_ADDRESS)
626                    };
627                    let application_id = {
628                        let mut runtime = context.db().0.runtime.lock().unwrap();
629                        let application_id = runtime.application_id()?;
630                        let source = application_id.into();
631                        let value = Amount::try_from(amount.0).map_err(EvmExecutionError::from)?;
632                        runtime.transfer(source, account, value)?;
633                        application_id
634                    };
635                    let source: Address = application_id.evm_address();
636                    revm_transfer(context, source, destination, amount.0)?;
637                }
638                Ok(vec![])
639            }
640        }
641    }
642
643    fn call_or_fail<Runtime: ContractRuntime>(
644        inputs: &InputsImpl,
645        context: &mut Ctx<'a, Runtime>,
646    ) -> Result<Vec<u8>, ExecutionError> {
647        let input = get_precompile_argument(context, inputs)?;
648        match bcs::from_bytes(&input)? {
649            RuntimePrecompile::Base(base_tag) => base_runtime_call(base_tag, context),
650            RuntimePrecompile::Contract(contract_tag) => {
651                Self::contract_runtime_call(contract_tag, context)
652            }
653            RuntimePrecompile::Service(_) => Err(EvmExecutionError::PrecompileError(
654                "Service tags are not available in GeneralContractCall".to_string(),
655            )
656            .into()),
657        }
658    }
659}
660
661#[derive(Debug, Default)]
662struct ServicePrecompile {
663    inner: EthPrecompiles,
664}
665
666impl<'a> ServicePrecompile {
667    fn service_runtime_call<Runtime: ServiceRuntime>(
668        request: ServiceRuntimePrecompile,
669        context: &mut Ctx<'a, Runtime>,
670    ) -> Result<Vec<u8>, ExecutionError> {
671        let mut runtime = context.db().0.runtime.lock().unwrap();
672        match request {
673            ServiceRuntimePrecompile::TryQueryApplication { target, argument } => {
674                ensure!(
675                    target != runtime.application_id()?,
676                    EvmExecutionError::NoSelfCall
677                );
678                runtime.try_query_application(target, argument)
679            }
680        }
681    }
682
683    fn call_or_fail<Runtime: ServiceRuntime>(
684        inputs: &InputsImpl,
685        context: &mut Ctx<'a, Runtime>,
686    ) -> Result<Vec<u8>, ExecutionError> {
687        let input = get_precompile_argument(context, inputs)?;
688        match bcs::from_bytes(&input)? {
689            RuntimePrecompile::Base(base_tag) => base_runtime_call(base_tag, context),
690            RuntimePrecompile::Contract(_) => Err(EvmExecutionError::PrecompileError(
691                "Contract calls are not available in GeneralServiceCall".to_string(),
692            )
693            .into()),
694            RuntimePrecompile::Service(service_tag) => {
695                Self::service_runtime_call(service_tag, context)
696            }
697        }
698    }
699}
700
701impl<'a, Runtime: ServiceRuntime> PrecompileProvider<Ctx<'a, Runtime>> for ServicePrecompile {
702    type Output = InterpreterResult;
703
704    fn set_spec(&mut self, spec: <<Ctx<'a, Runtime> as ContextTr>::Cfg as Cfg>::Spec) -> bool {
705        <EthPrecompiles as PrecompileProvider<Ctx<'a, Runtime>>>::set_spec(&mut self.inner, spec)
706    }
707
708    fn run(
709        &mut self,
710        context: &mut Ctx<'a, Runtime>,
711        address: &Address,
712        inputs: &InputsImpl,
713        is_static: bool,
714        gas_limit: u64,
715    ) -> Result<Option<InterpreterResult>, String> {
716        if address == &PRECOMPILE_ADDRESS {
717            let output = Self::call_or_fail(inputs, context)
718                .map_err(|error| format!("ServicePrecompile error: {error}"))?;
719            return Ok(Some(get_precompile_output(output, gas_limit)));
720        }
721        self.inner
722            .run(context, address, inputs, is_static, gas_limit)
723    }
724
725    fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
726        let mut addresses = self.inner.warm_addresses().collect::<Vec<Address>>();
727        addresses.push(PRECOMPILE_ADDRESS);
728        Box::new(addresses.into_iter())
729    }
730
731    fn contains(&self, address: &Address) -> bool {
732        address == &PRECOMPILE_ADDRESS || self.inner.contains(address)
733    }
734}
735
736fn map_result_create_outcome<Runtime: BaseRuntime>(
737    database: &DatabaseRuntime<Runtime>,
738    result: Result<Option<CreateOutcome>, ExecutionError>,
739) -> Option<CreateOutcome> {
740    match result {
741        Err(error) => {
742            database.insert_error(error);
743            // The use of Revert immediately stops the execution.
744            let result = InstructionResult::Revert;
745            let output = Bytes::default();
746            let gas = Gas::default();
747            let result = InterpreterResult {
748                result,
749                output,
750                gas,
751            };
752            Some(CreateOutcome {
753                result,
754                address: None,
755            })
756        }
757        Ok(result) => result,
758    }
759}
760
761fn map_result_call_outcome<Runtime: BaseRuntime>(
762    database: &DatabaseRuntime<Runtime>,
763    result: Result<Option<CallOutcome>, ExecutionError>,
764) -> Option<CallOutcome> {
765    match result {
766        Err(error) => {
767            database.insert_error(error);
768            // The use of Revert immediately stops the execution.
769            let result = InstructionResult::Revert;
770            let output = Bytes::default();
771            let gas = Gas::default();
772            let result = InterpreterResult {
773                result,
774                output,
775                gas,
776            };
777            let memory_offset = Range::default();
778            Some(CallOutcome {
779                result,
780                memory_offset,
781            })
782        }
783        Ok(result) => result,
784    }
785}
786
787fn get_interpreter_result(
788    result: &[u8],
789    inputs: &mut CallInputs,
790) -> Result<InterpreterResult, ExecutionError> {
791    let mut result = bcs::from_bytes::<InterpreterResult>(result)?;
792    // This effectively means that no cost is incurred by the call to another contract.
793    // This is fine since the costs are incurred by the other contract itself.
794    result.gas = Gas::new(inputs.gas_limit);
795    Ok(result)
796}
797
798struct CallInterceptorContract<Runtime> {
799    db: DatabaseRuntime<Runtime>,
800    // This is the contract address of the contract being created.
801    contract_address: Address,
802    precompile_addresses: BTreeSet<Address>,
803    error: Arc<Mutex<Option<U256>>>,
804}
805
806impl<Runtime> Clone for CallInterceptorContract<Runtime> {
807    fn clone(&self) -> Self {
808        Self {
809            db: self.db.clone(),
810            contract_address: self.contract_address,
811            precompile_addresses: self.precompile_addresses.clone(),
812            error: self.error.clone(),
813        }
814    }
815}
816
817impl<'a, Runtime: ContractRuntime> Inspector<Ctx<'a, Runtime>>
818    for CallInterceptorContract<Runtime>
819{
820    fn create(
821        &mut self,
822        context: &mut Ctx<'a, Runtime>,
823        inputs: &mut CreateInputs,
824    ) -> Option<CreateOutcome> {
825        let result = self.create_or_fail(context, inputs);
826        map_result_create_outcome(&self.db, result)
827    }
828
829    fn call(
830        &mut self,
831        context: &mut Ctx<'a, Runtime>,
832        inputs: &mut CallInputs,
833    ) -> Option<CallOutcome> {
834        let result = self.call_or_fail(context, inputs);
835        map_result_call_outcome(&self.db, result)
836    }
837}
838
839impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
840    /// Gets the expected `ApplicationId`. We need to transfer
841    /// native tokens before the application is created (see below).
842    /// Therefore, we need to pre-compute the obtained application ID.
843    fn get_expected_application_id(
844        runtime: &mut Runtime,
845        module_id: ModuleId,
846    ) -> Result<ApplicationId, ExecutionError> {
847        let chain_id = runtime.chain_id()?;
848        let block_height = runtime.block_height()?;
849        let application_index = runtime.peek_application_index()?;
850        let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
851        let required_application_ids = Vec::new();
852        let application_description = ApplicationDescription {
853            module_id,
854            creator_chain_id: chain_id,
855            block_height,
856            application_index,
857            parameters: parameters.clone(),
858            required_application_ids,
859        };
860        Ok(ApplicationId::from(&application_description))
861    }
862
863    /// Publishes the `inputs`.
864    fn publish_create_inputs(
865        context: &mut Ctx<'_, Runtime>,
866        inputs: &mut CreateInputs,
867    ) -> Result<ModuleId, ExecutionError> {
868        let contract = linera_base::data_types::Bytecode::new(inputs.init_code.to_vec());
869        let service = linera_base::data_types::Bytecode::new(vec![]);
870        let mut runtime = context.db().0.runtime.lock().unwrap();
871        runtime.publish_module(contract, service, VmRuntime::Evm)
872    }
873
874    /// The function `fn create` of the inspector trait is called
875    /// when a contract is going to be instantiated. Since the
876    /// function can have some error case which are not supported
877    /// in `fn create`, we call a `fn create_or_fail` that can
878    /// return errors.
879    /// When the database runtime is created, the EVM contract
880    /// may or may not have been created. Therefore, at startup
881    /// we have `is_revm_instantiated = false`. That boolean
882    /// can be updated after `set_is_initialized`.
883    ///
884    /// The inspector can do two things:
885    /// * It can change the inputs in `CreateInputs`. Here we
886    ///   change the address being created.
887    /// * It can return some specific CreateInput to be used.
888    ///
889    /// Therefore, the first case of the call is going to
890    /// be about the creation of the contract with just the
891    /// address being the one chosen by Linera.
892    ///
893    /// The second case occurs when the first contract has
894    /// been created and that contract starts making new
895    /// contracts.
896    /// In relation to bytecode, the following notions are
897    /// relevant:
898    /// * The bytecode is created from the compilation.
899    /// * The bytecode concatenated with the constructor
900    ///   argument. This is what is sent to EVM when we
901    ///   create a new contract.
902    /// * The deployed bytecode. This is essentially the
903    ///   bytecode minus the constructor code.
904    ///
905    /// In relation to that, the following points are
906    /// important:
907    /// * The inputs.init_code is formed by the concatenation
908    ///   of compiled bytecode + constructor argument.
909    /// * It is impossible to separate the compiled bytecode
910    ///   from the constructor argument. Think for example
911    ///   of the following two contracts:
912    ///   constructor(uint a, uint b) {
913    ///   value = a + b
914    ///   }
915    ///   or
916    ///   constructor(uint b) {
917    ///   value = 3 + b
918    ///   }
919    ///   Calling the first constructor with (3,4) leads
920    ///   to the same concatenation as the second constructor
921    ///   with input (4).
922    /// * It turns out that we do not need to determine the
923    ///   constructor argument.
924    /// * What needs to be determined is the deployed bytecode.
925    ///   This is stored in the AccountInfo entry. It is
926    ///   the result of the execution by the Revm interpreter
927    ///   and there is no way to do it without doing the execution.
928    ///
929    /// The strategy for creating the contract is thus:
930    /// * For the case of a new contract being created, we proceed
931    ///   like for services. We just adjust the address of the
932    ///   creation.
933    /// * In the second case, we first create the contract and
934    ///   service bytecode (empty, but not used) and then publish
935    ///   the module.
936    /// * The parameters is empty because the constructor argument
937    ///   have already put in the init_code.
938    /// * The instantiation argument is empty since an EVM contract
939    ///   creating a new contract will not support Linera features.
940    ///   This is simply not part of create/create2 in the EVM.
941    /// * That call to `create_application` leads to a creation of
942    ///   a new contract and so a call to `fn create_or_fail` in
943    ///   another instance of Revm.
944    /// * When returning the `CreateOutcome`, we need to have the
945    ///   deployed bytecode. This is implemented through a special
946    ///   call to `GET_DEPLOYED_BYTECODE_SELECTOR`. This is done
947    ///   with an `execute_operation`.
948    /// * Data is put together as a `Some(...)` which tells Revm
949    ///   that it does not need to execute the bytecode since the
950    ///   output is given to it.
951    ///
952    /// The fact that the creation of a contract can be done in a
953    /// parallel way to transferring native tokens to the contract
954    /// being created requires us to handle this as well.
955    /// * We cannot do a transfer from the calling contract with
956    ///   `deposit_funds` because we would not have the right
957    ///   to make the transfer.
958    /// * Therefore, we have to do the transfer before
959    ///   `create_application`. This forces us to know the
960    ///   `application_id` before it is created. This is done
961    ///   by building the `ApplicationDescription` and its hash.
962    fn create_or_fail(
963        &mut self,
964        context: &mut Ctx<'_, Runtime>,
965        inputs: &mut CreateInputs,
966    ) -> Result<Option<CreateOutcome>, ExecutionError> {
967        if !self.db.is_revm_instantiated {
968            self.db.is_revm_instantiated = true;
969            inputs.scheme = CreateScheme::Custom {
970                address: self.contract_address,
971            };
972            Ok(None)
973        } else {
974            if inputs.value != U256::ZERO {
975                // decrease the balance of the contract address by the expected amount.
976                // We put the tokens in FAUCET_ADDRESS because we cannot transfer to
977                // a contract that does not yet exist.
978                // It is a common construction. We can see that in ERC20 contract code
979                // for example for burning and minting.
980                revm_transfer(
981                    context,
982                    self.db.contract_address,
983                    FAUCET_ADDRESS,
984                    inputs.value,
985                )?;
986            }
987            let module_id = Self::publish_create_inputs(context, inputs)?;
988            let mut runtime = context.db().0.runtime.lock().unwrap();
989            let chain_id = runtime.chain_id()?;
990            let application_id = runtime.application_id()?;
991            let expected_application_id =
992                Self::get_expected_application_id(&mut runtime, module_id)?;
993            if inputs.value != U256::ZERO {
994                let amount = Amount::try_from(inputs.value).map_err(EvmExecutionError::from)?;
995                let destination = Account {
996                    chain_id,
997                    owner: expected_application_id.into(),
998                };
999                let source = application_id.into();
1000                runtime.transfer(source, destination, amount)?;
1001            }
1002            let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
1003            let evm_call = EvmInstantiation {
1004                value: inputs.value,
1005                argument: Vec::new(),
1006            };
1007            let argument = serde_json::to_vec(&evm_call)?;
1008            let required_application_ids = Vec::new();
1009            let created_application_id = runtime.create_application(
1010                module_id,
1011                parameters,
1012                argument,
1013                required_application_ids,
1014            )?;
1015            assert_eq!(expected_application_id, created_application_id);
1016            let argument = GET_DEPLOYED_BYTECODE_SELECTOR.to_vec();
1017            let deployed_bytecode: Vec<u8> =
1018                runtime.try_call_application(false, created_application_id, argument)?;
1019            let result = InterpreterResult {
1020                result: InstructionResult::Return, // Only possibility if no error occurred.
1021                output: Bytes::from(deployed_bytecode),
1022                gas: Gas::new(inputs.gas_limit),
1023            };
1024            let address = created_application_id.evm_address();
1025            let creation_outcome = CreateOutcome {
1026                result,
1027                address: Some(address),
1028            };
1029            Ok(Some(creation_outcome))
1030        }
1031    }
1032
1033    /// Every call to a contract passes by this function.
1034    /// Three kinds:
1035    /// --- Call to the EVM smart contract itself (the first call)
1036    /// --- Call to the PRECOMPILE smart contract.
1037    /// --- Call to other EVM smart contract
1038    ///
1039    /// The first case is handled by using Revm. This is
1040    /// when we call this contract.
1041    ///
1042    /// Calling the precompile is also handled by using Revm
1043    /// which would then use specific code for that purpose.
1044    ///
1045    /// Calling other EVM contracts is handled here and we have
1046    /// to produce `Some(_)` as output. Note that in the Evm
1047    /// transferring ethers is the same as calling a function.
1048    ///
1049    /// In Linera, transferring native tokens and calling a function are
1050    /// different operations. However, the block is accepted
1051    /// completely or not at all. Therefore, we can ensure the
1052    /// atomicity of the operations.
1053    fn call_or_fail(
1054        &mut self,
1055        context: &mut Ctx<'_, Runtime>,
1056        inputs: &mut CallInputs,
1057    ) -> Result<Option<CallOutcome>, ExecutionError> {
1058        if self.precompile_addresses.contains(&inputs.target_address)
1059            || inputs.target_address == self.contract_address
1060        {
1061            // Precompile calls are handled by the precompile code.
1062            // The EVM smart contract is being called
1063            return Ok(None);
1064        }
1065        // Handling the balances.
1066        if let CallValue::Transfer(value) = inputs.value {
1067            let source: AccountOwner = inputs.caller.into();
1068            let owner: AccountOwner = inputs.bytecode_address.into();
1069            if value != U256::ZERO {
1070                // In Linera, only non-zero transfers matter
1071                {
1072                    let mut runtime = context
1073                        .db()
1074                        .0
1075                        .runtime
1076                        .lock()
1077                        .expect("The lock should be possible");
1078                    let amount = Amount::try_from(value).map_err(EvmExecutionError::from)?;
1079                    let chain_id = runtime.chain_id()?;
1080                    let destination = Account { chain_id, owner };
1081                    runtime.transfer(source, destination, amount)?;
1082                }
1083                revm_transfer(context, inputs.caller, inputs.target_address, value)?;
1084            }
1085        }
1086        // Other smart contracts calls are handled by the runtime
1087        let target = address_to_user_application_id(inputs.target_address);
1088        let (argument, n_input) = get_call_contract_argument(context, inputs)?;
1089        let contract_call = {
1090            if n_input > 0 {
1091                // The input is non-empty. It is a contract call.
1092                true
1093            } else {
1094                // In case of empty input, we have two scenarios:
1095                // * We are calling an EVM application. In that case it has non-empty
1096                //   storage (at least the deployed code)
1097                // * It is a user account. In that case it has empty storage.
1098                let mut runtime = self.db.runtime.lock().unwrap();
1099                !runtime.has_empty_storage(target)?
1100            }
1101        };
1102        let result = if contract_call {
1103            let authenticated = true;
1104            let result = {
1105                let mut runtime = self.db.runtime.lock().unwrap();
1106                runtime.try_call_application(authenticated, target, argument)?
1107            };
1108            get_interpreter_result(&result, inputs)?
1109        } else {
1110            // User account, no call needed.
1111            InterpreterResult {
1112                result: InstructionResult::Stop,
1113                output: Bytes::default(),
1114                gas: Gas::new(inputs.gas_limit),
1115            }
1116        };
1117        let call_outcome = CallOutcome {
1118            result,
1119            memory_offset: inputs.return_memory_offset.clone(),
1120        };
1121        Ok(Some(call_outcome))
1122    }
1123}
1124
1125struct CallInterceptorService<Runtime> {
1126    db: DatabaseRuntime<Runtime>,
1127    // This is the contract address of the contract being created.
1128    contract_address: Address,
1129    precompile_addresses: BTreeSet<Address>,
1130}
1131
1132impl<Runtime> Clone for CallInterceptorService<Runtime> {
1133    fn clone(&self) -> Self {
1134        Self {
1135            db: self.db.clone(),
1136            contract_address: self.contract_address,
1137            precompile_addresses: self.precompile_addresses.clone(),
1138        }
1139    }
1140}
1141
1142impl<'a, Runtime: ServiceRuntime> Inspector<Ctx<'a, Runtime>> for CallInterceptorService<Runtime> {
1143    /// See below on `fn create_or_fail`.
1144    fn create(
1145        &mut self,
1146        context: &mut Ctx<'a, Runtime>,
1147        inputs: &mut CreateInputs,
1148    ) -> Option<CreateOutcome> {
1149        let result = self.create_or_fail(context, inputs);
1150        map_result_create_outcome(&self.db, result)
1151    }
1152
1153    /// See below on `fn call_or_fail`.
1154    fn call(
1155        &mut self,
1156        context: &mut Ctx<'a, Runtime>,
1157        inputs: &mut CallInputs,
1158    ) -> Option<CallOutcome> {
1159        let result = self.call_or_fail(context, inputs);
1160        map_result_call_outcome(&self.db, result)
1161    }
1162}
1163
1164impl<Runtime: ServiceRuntime> CallInterceptorService<Runtime> {
1165    /// The function `fn create` of the inspector trait is called
1166    /// when a contract is going to be instantiated. Since the
1167    /// function can have some error case which are not supported
1168    /// in `fn create`, we call a `fn create_or_fail` that can
1169    /// return errors.
1170    /// When the database runtime is created, the EVM contract
1171    /// may or may not have been created. Therefore, at startup
1172    /// we have `is_revm_instantiated = false`. That boolean
1173    /// can be updated after `set_is_initialized`.
1174    ///
1175    /// The inspector can do two things:
1176    /// * It can change the inputs in `CreateInputs`. Here we
1177    ///   change the address being created.
1178    /// * It can return some specific CreateInput to be used.
1179    ///
1180    /// Therefore, the first case of the call is going to
1181    /// be about the creation of the contract with just the
1182    /// address being the one chosen by Linera.
1183    /// The second case of creating a new contract does not
1184    /// apply in services and so lead to an error.
1185    fn create_or_fail(
1186        &mut self,
1187        _context: &mut Ctx<'_, Runtime>,
1188        inputs: &mut CreateInputs,
1189    ) -> Result<Option<CreateOutcome>, ExecutionError> {
1190        if !self.db.is_revm_instantiated {
1191            self.db.is_revm_instantiated = true;
1192            inputs.scheme = CreateScheme::Custom {
1193                address: self.contract_address,
1194            };
1195            Ok(None)
1196        } else {
1197            Err(EvmExecutionError::NoContractCreationInService.into())
1198        }
1199    }
1200
1201    /// Every call to a contract passes by this function.
1202    /// Three kinds:
1203    /// --- Call to the EVM smart contract itself
1204    /// --- Call to the PRECOMPILE smart contract.
1205    /// --- Call to other EVM smart contract
1206    ///
1207    /// The first kind is the call to the contract itself like
1208    /// constructor or from an external call.
1209    /// The second kind is precompile calls. This include the
1210    /// classic one but also the one that accesses the Linera
1211    /// functionalities.
1212    /// The last kind is the calls to other EVM smart contracts.
1213    fn call_or_fail(
1214        &mut self,
1215        context: &mut Ctx<'_, Runtime>,
1216        inputs: &mut CallInputs,
1217    ) -> Result<Option<CallOutcome>, ExecutionError> {
1218        if self.precompile_addresses.contains(&inputs.target_address)
1219            || inputs.target_address == self.contract_address
1220        {
1221            // Precompile calls are handled by the precompile code.
1222            // The EVM smart contract is being called
1223            return Ok(None);
1224        }
1225        // Other smart contracts calls are handled by the runtime
1226        let target = address_to_user_application_id(inputs.target_address);
1227        let argument = get_call_service_argument(context, inputs)?;
1228        let result = {
1229            let evm_query = EvmQuery::Query(argument);
1230            let evm_query = serde_json::to_vec(&evm_query)?;
1231            let mut runtime = self.db.runtime.lock().unwrap();
1232            runtime.try_query_application(target, evm_query)?
1233        };
1234        let call_outcome = CallOutcome {
1235            result: get_interpreter_result(&result, inputs)?,
1236            memory_offset: inputs.return_memory_offset.clone(),
1237        };
1238        Ok(Some(call_outcome))
1239    }
1240}
1241
1242pub struct RevmContractInstance<Runtime> {
1243    module: Vec<u8>,
1244    db: DatabaseRuntime<Runtime>,
1245}
1246
1247#[derive(Debug)]
1248enum EvmTxKind {
1249    Create,
1250    Call,
1251}
1252
1253#[derive(Debug)]
1254struct ExecutionResultSuccess {
1255    reason: SuccessReason,
1256    gas_final: u64,
1257    logs: Vec<Log>,
1258    output: Output,
1259}
1260
1261impl ExecutionResultSuccess {
1262    fn interpreter_result_and_logs(self) -> Result<(u64, Vec<u8>, Vec<Log>), ExecutionError> {
1263        let result: InstructionResult = self.reason.into();
1264        let Output::Call(output) = self.output else {
1265            unreachable!("The output should have been created from a EvmTxKind::Call");
1266        };
1267        let gas = Gas::new(0);
1268        let result = InterpreterResult {
1269            result,
1270            output,
1271            gas,
1272        };
1273        let result = bcs::to_bytes(&result)?;
1274        Ok((self.gas_final, result, self.logs))
1275    }
1276
1277    fn output_and_logs(self) -> (u64, Vec<u8>, Vec<Log>) {
1278        let Output::Call(output) = self.output else {
1279            unreachable!("The output should have been created from a EvmTxKind::Call");
1280        };
1281        let output = output.as_ref().to_vec();
1282        (self.gas_final, output, self.logs)
1283    }
1284
1285    // Checks that the contract has been correctly instantiated
1286    fn check_contract_initialization(&self, expected_address: Address) -> Result<(), String> {
1287        // Checks that the output is the expected one.
1288        let Output::Create(_, contract_address) = self.output else {
1289            return Err("Input should be ExmTxKind::Create".to_string());
1290        };
1291        // Checks that the contract address exists.
1292        let contract_address = contract_address.ok_or("Deployment failed")?;
1293        // Checks that the created contract address is the one of the `ApplicationId`.
1294        if contract_address == expected_address {
1295            Ok(())
1296        } else {
1297            Err("Contract address is not the same as ApplicationId".to_string())
1298        }
1299    }
1300}
1301
1302impl<Runtime> UserContract for RevmContractInstance<Runtime>
1303where
1304    Runtime: ContractRuntime,
1305{
1306    fn instantiate(&mut self, argument: Vec<u8>) -> Result<(), ExecutionError> {
1307        self.db.set_contract_address()?;
1308        let caller = self.get_msg_address()?;
1309        let instantiation_argument = serde_json::from_slice::<EvmInstantiation>(&argument)?;
1310        self.initialize_contract(instantiation_argument.value, caller)?;
1311        if has_selector(&self.module, INSTANTIATE_SELECTOR) {
1312            let argument = get_revm_instantiation_bytes(instantiation_argument.argument);
1313            let result = self.transact_commit(EvmTxKind::Call, argument, U256::ZERO, caller)?;
1314            self.write_logs(result.logs, "instantiate")?;
1315        }
1316        Ok(())
1317    }
1318
1319    fn execute_operation(&mut self, operation: Vec<u8>) -> Result<Vec<u8>, ExecutionError> {
1320        self.db.set_contract_address()?;
1321        ensure_message_length(operation.len(), 4)?;
1322        if operation == GET_DEPLOYED_BYTECODE_SELECTOR {
1323            return self.db.get_deployed_bytecode();
1324        }
1325        let caller = self.get_msg_address()?;
1326        let (gas_final, output, logs) = if &operation[..4] == INTERPRETER_RESULT_SELECTOR {
1327            ensure_message_length(operation.len(), 8)?;
1328            forbid_execute_operation_origin(&operation[4..8])?;
1329            let evm_call = bcs::from_bytes::<EvmOperation>(&operation[4..])?;
1330            let result = self.init_transact_commit(evm_call.argument, evm_call.value, caller)?;
1331            result.interpreter_result_and_logs()?
1332        } else {
1333            forbid_execute_operation_origin(&operation[..4])?;
1334            let evm_call = bcs::from_bytes::<EvmOperation>(&operation)?;
1335            let result = self.init_transact_commit(evm_call.argument, evm_call.value, caller)?;
1336            result.output_and_logs()
1337        };
1338        self.consume_fuel(gas_final)?;
1339        self.write_logs(logs, "operation")?;
1340        Ok(output)
1341    }
1342
1343    fn execute_message(&mut self, message: Vec<u8>) -> Result<(), ExecutionError> {
1344        self.db.set_contract_address()?;
1345        ensure_selector_presence(
1346            &self.module,
1347            EXECUTE_MESSAGE_SELECTOR,
1348            "function execute_message(bytes)",
1349        )?;
1350        let operation = get_revm_execute_message_bytes(message);
1351        let caller = self.get_msg_address()?;
1352        let value = U256::ZERO;
1353        self.execute_no_return_operation(operation, "message", value, caller)
1354    }
1355
1356    fn process_streams(&mut self, streams: Vec<StreamUpdate>) -> Result<(), ExecutionError> {
1357        self.db.set_contract_address()?;
1358        let operation = get_revm_process_streams_bytes(streams);
1359        ensure_selector_presence(
1360            &self.module,
1361            PROCESS_STREAMS_SELECTOR,
1362            "function process_streams(Linera.StreamUpdate[] memory streams)",
1363        )?;
1364        // For process_streams, authenticated_owner and authenticated_called_id are None.
1365        let caller = Address::ZERO;
1366        let value = U256::ZERO;
1367        self.execute_no_return_operation(operation, "process_streams", value, caller)
1368    }
1369
1370    fn finalize(&mut self) -> Result<(), ExecutionError> {
1371        Ok(())
1372    }
1373}
1374
1375fn process_execution_result(
1376    storage_stats: StorageStats,
1377    result: ExecutionResult,
1378) -> Result<ExecutionResultSuccess, EvmExecutionError> {
1379    match result {
1380        ExecutionResult::Success {
1381            reason,
1382            gas_used,
1383            gas_refunded,
1384            logs,
1385            output,
1386        } => {
1387            let mut gas_final = gas_used;
1388            gas_final -= storage_stats.storage_costs();
1389            assert_eq!(gas_refunded, storage_stats.storage_refund());
1390            if !matches!(reason, SuccessReason::Return) {
1391                Err(EvmExecutionError::NoReturnInterpreter {
1392                    reason,
1393                    gas_used,
1394                    gas_refunded,
1395                    logs,
1396                    output,
1397                })
1398            } else {
1399                Ok(ExecutionResultSuccess {
1400                    reason,
1401                    gas_final,
1402                    logs,
1403                    output,
1404                })
1405            }
1406        }
1407        ExecutionResult::Revert { gas_used, output } => {
1408            Err(EvmExecutionError::Revert { gas_used, output })
1409        }
1410        ExecutionResult::Halt { gas_used, reason } => {
1411            Err(EvmExecutionError::Halt { gas_used, reason })
1412        }
1413    }
1414}
1415
1416impl<Runtime> RevmContractInstance<Runtime>
1417where
1418    Runtime: ContractRuntime,
1419{
1420    pub fn prepare(module: Vec<u8>, runtime: Runtime) -> Self {
1421        let db = DatabaseRuntime::new(runtime);
1422        Self { module, db }
1423    }
1424
1425    fn execute_no_return_operation(
1426        &mut self,
1427        operation: Vec<u8>,
1428        origin: &str,
1429        value: U256,
1430        caller: Address,
1431    ) -> Result<(), ExecutionError> {
1432        let result = self.init_transact_commit(operation, value, caller)?;
1433        let (gas_final, output, logs) = result.output_and_logs();
1434        self.consume_fuel(gas_final)?;
1435        self.write_logs(logs, origin)?;
1436        assert_eq!(output.len(), 0);
1437        Ok(())
1438    }
1439
1440    /// Executes the transaction. If needed initializes the contract.
1441    fn init_transact_commit(
1442        &mut self,
1443        vec: Vec<u8>,
1444        value: U256,
1445        caller: Address,
1446    ) -> Result<ExecutionResultSuccess, ExecutionError> {
1447        // An application can be instantiated in Linera sense, but not in EVM sense,
1448        // that is the contract entries corresponding to the deployed contract may
1449        // be missing.
1450        if !self.db.set_is_initialized()? {
1451            self.initialize_contract(U256::ZERO, caller)?;
1452        }
1453        self.transact_commit(EvmTxKind::Call, vec, value, caller)
1454    }
1455
1456    /// Initializes the contract.
1457    fn initialize_contract(&mut self, value: U256, caller: Address) -> Result<(), ExecutionError> {
1458        let mut vec_init = self.module.clone();
1459        let constructor_argument = self.db.constructor_argument()?;
1460        vec_init.extend_from_slice(&constructor_argument);
1461        let result = self.transact_commit(EvmTxKind::Create, vec_init, value, caller)?;
1462        result
1463            .check_contract_initialization(self.db.contract_address)
1464            .map_err(EvmExecutionError::IncorrectContractCreation)?;
1465        self.write_logs(result.logs, "deploy")
1466    }
1467
1468    /// Computes the address used in the `msg.sender` variable.
1469    /// It is computed in the following way:
1470    /// * If a Wasm contract calls an EVM contract then it is `Address::ZERO`.
1471    /// * If an EVM contract calls an EVM contract it is the address of the contract.
1472    /// * If a user having an `AccountOwner::Address32` address calls an EVM contract
1473    ///   then it is `Address::ZERO`.
1474    /// * If a user having an `AccountOwner::Address20` address calls an EVM contract
1475    ///   then it is this address.
1476    ///
1477    /// By doing this we ensure that EVM smart contracts works in the same way as
1478    /// on the EVM and that users and contracts outside of that realm can still
1479    /// call EVM smart contracts.
1480    fn get_msg_address(&self) -> Result<Address, ExecutionError> {
1481        let mut runtime = self.db.runtime.lock().unwrap();
1482        let application_id = runtime.authenticated_caller_id()?;
1483        if let Some(application_id) = application_id {
1484            return Ok(if application_id.is_evm() {
1485                application_id.evm_address()
1486            } else {
1487                Address::ZERO
1488            });
1489        };
1490        let account_owner = runtime.authenticated_owner()?;
1491        if let Some(AccountOwner::Address20(address)) = account_owner {
1492            return Ok(Address::from(address));
1493        };
1494        Ok(ZERO_ADDRESS)
1495    }
1496
1497    fn transact_commit(
1498        &mut self,
1499        ch: EvmTxKind,
1500        input: Vec<u8>,
1501        value: U256,
1502        caller: Address,
1503    ) -> Result<ExecutionResultSuccess, ExecutionError> {
1504        self.db.caller = caller;
1505        self.db.value = value;
1506        self.db.deposit_funds()?;
1507        let data = Bytes::from(input);
1508        let kind = match ch {
1509            EvmTxKind::Create => TxKind::Create,
1510            EvmTxKind::Call => TxKind::Call(self.db.contract_address),
1511        };
1512        let inspector = CallInterceptorContract {
1513            db: self.db.clone(),
1514            contract_address: self.db.contract_address,
1515            precompile_addresses: precompile_addresses(),
1516            error: Arc::new(Mutex::new(None)),
1517        };
1518        let block_env = self.db.get_contract_block_env()?;
1519        let (max_size_evm_contract, gas_limit) = {
1520            let mut runtime = self.db.runtime.lock().unwrap();
1521            let gas_limit = runtime.remaining_fuel(VmRuntime::Evm)?;
1522            let max_size_evm_contract = runtime.maximum_blob_size()? as usize;
1523            (max_size_evm_contract, gas_limit)
1524        };
1525        let nonce = self.db.get_nonce(&caller)?;
1526        let result = {
1527            let mut ctx: revm_context::Context<
1528                BlockEnv,
1529                _,
1530                _,
1531                _,
1532                Journal<WrapDatabaseRef<&mut DatabaseRuntime<Runtime>>>,
1533                (),
1534            > = revm_context::Context::<BlockEnv, _, _, _, _, _>::new(
1535                WrapDatabaseRef(&mut self.db),
1536                SpecId::PRAGUE,
1537            )
1538            .with_block(block_env);
1539            ctx.cfg.limit_contract_code_size = Some(max_size_evm_contract);
1540            let instructions = EthInstructions::new_mainnet();
1541            let mut evm = Evm::new_with_inspector(
1542                ctx,
1543                inspector.clone(),
1544                instructions,
1545                ContractPrecompile::default(),
1546            );
1547            evm.inspect_commit(
1548                TxEnv {
1549                    kind,
1550                    data,
1551                    nonce,
1552                    gas_limit,
1553                    caller,
1554                    value,
1555                    ..TxEnv::default()
1556                },
1557                inspector.clone(),
1558            )
1559            .map_err(|error| {
1560                let error = format!("{:?}", error);
1561                EvmExecutionError::TransactCommitError(error)
1562            })
1563        }?;
1564        self.db.process_any_error()?;
1565        let storage_stats = self.db.take_storage_stats();
1566        self.db.commit_changes()?;
1567        let result = process_execution_result(storage_stats, result)?;
1568        Ok(result)
1569    }
1570
1571    fn consume_fuel(&mut self, gas_final: u64) -> Result<(), ExecutionError> {
1572        let mut runtime = self.db.runtime.lock().unwrap();
1573        runtime.consume_fuel(gas_final, VmRuntime::Evm)
1574    }
1575
1576    fn write_logs(&mut self, logs: Vec<Log>, origin: &str) -> Result<(), ExecutionError> {
1577        // TODO(#3758): Extracting Ethereum events from the Linera events.
1578        if !logs.is_empty() {
1579            let mut runtime = self.db.runtime.lock().unwrap();
1580            let block_height = runtime.block_height()?;
1581            let stream_name = bcs::to_bytes("ethereum_event")?;
1582            let stream_name = StreamName(stream_name);
1583            for log in &logs {
1584                let value = bcs::to_bytes(&(origin, block_height.0, log))?;
1585                runtime.emit(stream_name.clone(), value)?;
1586            }
1587        }
1588        Ok(())
1589    }
1590}
1591
1592pub struct RevmServiceInstance<Runtime> {
1593    module: Vec<u8>,
1594    db: DatabaseRuntime<Runtime>,
1595}
1596
1597impl<Runtime> RevmServiceInstance<Runtime>
1598where
1599    Runtime: ServiceRuntime,
1600{
1601    pub fn prepare(module: Vec<u8>, runtime: Runtime) -> Self {
1602        let db = DatabaseRuntime::new(runtime);
1603        Self { module, db }
1604    }
1605}
1606
1607impl<Runtime> UserService for RevmServiceInstance<Runtime>
1608where
1609    Runtime: ServiceRuntime,
1610{
1611    fn handle_query(&mut self, argument: Vec<u8>) -> Result<Vec<u8>, ExecutionError> {
1612        self.db.set_contract_address()?;
1613        let evm_query = serde_json::from_slice(&argument)?;
1614        let query = match evm_query {
1615            EvmQuery::Query(vec) => vec,
1616            EvmQuery::Operation(operation) => {
1617                let mut runtime = self.db.runtime.lock().unwrap();
1618                runtime.schedule_operation(operation)?;
1619                return Ok(Vec::new());
1620            }
1621            EvmQuery::Operations(operations) => {
1622                let mut runtime = self.db.runtime.lock().unwrap();
1623                for operation in operations {
1624                    runtime.schedule_operation(operation)?;
1625                }
1626                return Ok(Vec::new());
1627            }
1628        };
1629
1630        ensure_message_length(query.len(), 4)?;
1631        // We drop the logs since the "eth_call" execution does not return any log.
1632        // Also, for handle_query, we do not have associated costs.
1633        // More generally, there is gas costs associated to service operation.
1634        let answer = if &query[..4] == INTERPRETER_RESULT_SELECTOR {
1635            let result = self.init_transact(query[4..].to_vec())?;
1636            let (_gas_final, answer, _logs) = result.interpreter_result_and_logs()?;
1637            answer
1638        } else {
1639            let result = self.init_transact(query)?;
1640            let (_gas_final, output, _logs) = result.output_and_logs();
1641            serde_json::to_vec(&output)?
1642        };
1643        Ok(answer)
1644    }
1645}
1646
1647impl<Runtime> RevmServiceInstance<Runtime>
1648where
1649    Runtime: ServiceRuntime,
1650{
1651    fn init_transact(&mut self, vec: Vec<u8>) -> Result<ExecutionResultSuccess, ExecutionError> {
1652        // In case of a shared application, we need to instantiate it first
1653        // However, since in ServiceRuntime, we cannot modify the storage,
1654        // therefore the compiled contract is saved in the changes.
1655        if !self.db.set_is_initialized()? {
1656            let changes = {
1657                let mut vec_init = self.module.clone();
1658                let constructor_argument = self.db.constructor_argument()?;
1659                vec_init.extend_from_slice(&constructor_argument);
1660                let (result, changes) = self.transact(TxKind::Create, vec_init)?;
1661                result
1662                    .check_contract_initialization(self.db.contract_address)
1663                    .map_err(EvmExecutionError::IncorrectContractCreation)?;
1664                changes
1665            };
1666            self.db.changes = changes;
1667        }
1668        ensure_message_length(vec.len(), 4)?;
1669        forbid_execute_operation_origin(&vec[..4])?;
1670        let kind = TxKind::Call(self.db.contract_address);
1671        let (execution_result, _) = self.transact(kind, vec)?;
1672        Ok(execution_result)
1673    }
1674
1675    fn transact(
1676        &mut self,
1677        kind: TxKind,
1678        input: Vec<u8>,
1679    ) -> Result<(ExecutionResultSuccess, EvmState), ExecutionError> {
1680        let caller = SERVICE_ADDRESS;
1681        let value = U256::ZERO;
1682        self.db.caller = caller;
1683        self.db.value = value;
1684        let data = Bytes::from(input);
1685        let block_env = self.db.get_service_block_env()?;
1686        let inspector = CallInterceptorService {
1687            db: self.db.clone(),
1688            contract_address: self.db.contract_address,
1689            precompile_addresses: precompile_addresses(),
1690        };
1691        let max_size_evm_contract = {
1692            let mut runtime = self.db.runtime.lock().unwrap();
1693            runtime.maximum_blob_size()? as usize
1694        };
1695        let nonce = self.db.get_nonce(&caller)?;
1696        let result_state = {
1697            let mut ctx: revm_context::Context<
1698                BlockEnv,
1699                _,
1700                _,
1701                _,
1702                Journal<WrapDatabaseRef<&mut DatabaseRuntime<Runtime>>>,
1703                (),
1704            > = revm_context::Context::<BlockEnv, _, _, _, _, _>::new(
1705                WrapDatabaseRef(&mut self.db),
1706                SpecId::PRAGUE,
1707            )
1708            .with_block(block_env);
1709            ctx.cfg.limit_contract_code_size = Some(max_size_evm_contract);
1710            let instructions = EthInstructions::new_mainnet();
1711            let mut evm = Evm::new_with_inspector(
1712                ctx,
1713                inspector.clone(),
1714                instructions,
1715                ServicePrecompile::default(),
1716            );
1717            evm.inspect(
1718                TxEnv {
1719                    kind,
1720                    data,
1721                    nonce,
1722                    value,
1723                    caller,
1724                    gas_limit: EVM_SERVICE_GAS_LIMIT,
1725                    ..TxEnv::default()
1726                },
1727                inspector,
1728            )
1729            .map_err(|error| {
1730                let error = format!("{:?}", error);
1731                EvmExecutionError::TransactCommitError(error)
1732            })
1733        }?;
1734        self.db.process_any_error()?;
1735        let storage_stats = self.db.take_storage_stats();
1736        Ok((
1737            process_execution_result(storage_stats, result_state.result)?,
1738            result_state.state,
1739        ))
1740    }
1741}